Putty -> Crypto++
This commit is contained in:
+104
-143
@@ -3,11 +3,27 @@
|
||||
#include "RageUtil.h"
|
||||
#include "RageLog.h"
|
||||
#include "PrefsManager.h"
|
||||
#include "RageFile.h"
|
||||
|
||||
#include "crypto/CryptRSA.h"
|
||||
#include "crypto/CryptRand.h"
|
||||
#include "crypto/CryptMD5.h"
|
||||
// crypt headers
|
||||
#include "CryptHelpers.h"
|
||||
#include "crypto51/sha.h"
|
||||
#include "crypto51/channels.h"
|
||||
#include "crypto51/hex.h"
|
||||
#include "crypto51/rsa.h"
|
||||
#include "crypto51/md5.h"
|
||||
#include "crypto51/osrng.h"
|
||||
#include <memory>
|
||||
|
||||
using namespace CryptoPP;
|
||||
using namespace std;
|
||||
|
||||
#ifdef WIN32
|
||||
#ifdef DEBUG
|
||||
#pragma comment(lib, "crypto51\\Release\\cryptlib.lib")
|
||||
#else
|
||||
#pragma comment(lib, "crypto51\\Debug\\cryptlib.lib")
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static const CString PRIVATE_KEY_PATH = "Data/private.key.rsa";
|
||||
static const CString PUBLIC_KEY_PATH = "Data/public.key.rsa";
|
||||
@@ -17,17 +33,19 @@ CryptManager* CRYPTMAN = NULL; // global and accessable from anywhere in our pro
|
||||
|
||||
CryptManager::CryptManager()
|
||||
{
|
||||
if( !PREFSMAN->m_bSignProfileData )
|
||||
return;
|
||||
|
||||
//
|
||||
// generate keys if none are available
|
||||
//
|
||||
if( !DoesFileExist(PRIVATE_KEY_PATH) || !DoesFileExist(PUBLIC_KEY_PATH) )
|
||||
/* This is crashing in crypto51/integer.cpp CryptoPP::RecursiveInverseModPower2
|
||||
* in Linux. -glenn */
|
||||
if( PREFSMAN->m_bSignProfileData )
|
||||
{
|
||||
LOG->Warn( "Keys missing. Generating new keys" );
|
||||
GenerateRSAKey( KEY_LENGTH, PRIVATE_KEY_PATH, PUBLIC_KEY_PATH, "aoksdjaksd" );
|
||||
FlushDirCache();
|
||||
if( !DoesFileExist(PRIVATE_KEY_PATH) || !DoesFileExist(PUBLIC_KEY_PATH) )
|
||||
{
|
||||
LOG->Warn( "Keys missing. Generating new keys" );
|
||||
GenerateRSAKey( KEY_LENGTH, PRIVATE_KEY_PATH, PUBLIC_KEY_PATH, "aoksdjaksd" );
|
||||
FlushDirCache();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,119 +58,80 @@ void CryptManager::GenerateRSAKey( unsigned int keyLength, CString privFilename,
|
||||
{
|
||||
ASSERT( PREFSMAN->m_bSignProfileData );
|
||||
|
||||
// Does the RNG need to be inited and seeded every time?
|
||||
random_init();
|
||||
random_add_noise( seed );
|
||||
AutoSeededRandomPool rng;
|
||||
|
||||
RSAKey key;
|
||||
key.Generate( keyLength );
|
||||
RSAES_OAEP_SHA_Decryptor priv(rng, keyLength);
|
||||
RageFileSink privFile(privFilename);
|
||||
priv.DEREncode(privFile);
|
||||
privFile.MessageEnd();
|
||||
|
||||
RageFile out;
|
||||
|
||||
CString sPublic;
|
||||
key.PublicBlob( sPublic );
|
||||
if( !out.Open( pubFilename, RageFile::WRITE ) )
|
||||
RageException::Throw( "Error opening %s: %s", pubFilename.c_str(), out.GetError().c_str() );
|
||||
out.Write( sPublic );
|
||||
out.Close();
|
||||
|
||||
CString sPrivate;
|
||||
key.PrivateBlob( sPrivate );
|
||||
if( !out.Open( privFilename, RageFile::WRITE ) )
|
||||
RageException::Throw( "Error opening %s: %s", privFilename.c_str(), out.GetError().c_str() );
|
||||
out.Write( sPrivate );
|
||||
out.Close();
|
||||
RSAES_OAEP_SHA_Encryptor pub(priv);
|
||||
RageFileSink pubFile(pubFilename);
|
||||
pub.DEREncode(pubFile);
|
||||
pubFile.MessageEnd();
|
||||
}
|
||||
|
||||
void CryptManager::SignFileToFile( CString sPath, CString sSignatureFilename )
|
||||
void CryptManager::SignFileToFile( CString sPath, CString sSignatureFile )
|
||||
{
|
||||
if( sSignatureFilename == "" )
|
||||
sSignatureFilename = sPath + SIGNATURE_APPEND;
|
||||
|
||||
LOG->Trace("SignFile(%s)", sPath.c_str());
|
||||
ASSERT( PREFSMAN->m_bSignProfileData );
|
||||
|
||||
if( !IsAFile(PRIVATE_KEY_PATH) )
|
||||
CString sPrivFilename = PRIVATE_KEY_PATH;
|
||||
CString sMessageFilename = sPath;;
|
||||
if( sSignatureFile.empty() )
|
||||
sSignatureFile = sPath + SIGNATURE_APPEND;
|
||||
|
||||
if( !IsAFile(sPrivFilename) )
|
||||
return;
|
||||
|
||||
if( !IsAFile(sPath) )
|
||||
if( !IsAFile(sMessageFilename) )
|
||||
return;
|
||||
|
||||
const CString sig = Sign( sPath );
|
||||
// CAREFUL: These classes can throw all kinds of exceptions. Should this
|
||||
// be wrapped in a try catch?
|
||||
|
||||
RageFile out;
|
||||
if( !out.Open( sSignatureFilename, RageFile::WRITE ) )
|
||||
RageException::Throw( "Error opening %s: %s", sSignatureFilename.c_str(), out.GetError().c_str() );
|
||||
out.Write( sig );
|
||||
RageFileSource privFile(sPrivFilename, true);
|
||||
RSASSA_PKCS1v15_SHA_Signer priv(privFile);
|
||||
AutoSeededRandomPool rng;
|
||||
RageFileSource f(sMessageFilename, true, new SignerFilter(rng, priv, new RageFileSink(sSignatureFile)));
|
||||
}
|
||||
|
||||
bool CryptManager::VerifyFileWithFile( CString sPath, CString sSignatureFilename )
|
||||
{
|
||||
if( !IsAFile(sPath) )
|
||||
return false;
|
||||
|
||||
if( sSignatureFilename == "" )
|
||||
sSignatureFilename = sPath + SIGNATURE_APPEND;
|
||||
|
||||
LOG->Trace("VerifyFile(%s)", sPath.c_str());
|
||||
ASSERT( PREFSMAN->m_bSignProfileData );
|
||||
|
||||
if( !IsAFile(PUBLIC_KEY_PATH) )
|
||||
return false;
|
||||
|
||||
if( !IsAFile(sSignatureFilename) )
|
||||
return false;
|
||||
|
||||
CString sig;
|
||||
{
|
||||
RageFile in;
|
||||
if( !in.Open( sSignatureFilename, RageFile::READ ) )
|
||||
RageException::Throw( "Error opening %s: %s", sSignatureFilename.c_str(), in.GetError().c_str() );
|
||||
in.Read( sig );
|
||||
}
|
||||
|
||||
return Verify( sPath, sig );
|
||||
}
|
||||
|
||||
CString CryptManager::Sign( CString sPath )
|
||||
bool CryptManager::VerifyFileWithFile( CString sPath, CString sSignatureFile )
|
||||
{
|
||||
ASSERT( PREFSMAN->m_bSignProfileData );
|
||||
|
||||
if( !IsAFile(PRIVATE_KEY_PATH) )
|
||||
return "";
|
||||
CString sPubFilename = PUBLIC_KEY_PATH;
|
||||
CString sMessageFilename = sPath;;
|
||||
if( sSignatureFile.empty() )
|
||||
sSignatureFile = sPath + SIGNATURE_APPEND;
|
||||
|
||||
if( !IsAFile(sPath) )
|
||||
return "";
|
||||
if( !IsAFile(sPubFilename) )
|
||||
return false;
|
||||
|
||||
CString data;
|
||||
{
|
||||
RageFile in;
|
||||
if( !in.Open( sPath, RageFile::READ ) )
|
||||
RageException::Throw( "Error opening %s: %s", sPath.c_str(), in.GetError().c_str() );
|
||||
in.Read( data );
|
||||
}
|
||||
if( !IsAFile(sSignatureFile) )
|
||||
return false;
|
||||
|
||||
RSAKey key;
|
||||
{
|
||||
RageFile keyfile;
|
||||
if( !keyfile.Open( PRIVATE_KEY_PATH ) )
|
||||
RageException::Throw( "Error opening %s: %s", PRIVATE_KEY_PATH.c_str(), keyfile.GetError().c_str() );
|
||||
CString private_blob;
|
||||
keyfile.Read( private_blob );
|
||||
key.LoadFromPrivateBlob( private_blob );
|
||||
}
|
||||
// CAREFUL: These classes can throw all kinds of exceptions. Should this
|
||||
// be wrapped in a try catch?
|
||||
|
||||
CString sig;
|
||||
key.Sign( data, sig );
|
||||
/* XXX: This is opening sPubFilename for RageFile::WRITE instead of READ. */
|
||||
RageFileSource pubFile(sPubFilename, true);
|
||||
RSASSA_PKCS1v15_SHA_Verifier pub(pubFile);
|
||||
|
||||
return sig;
|
||||
RageFileSource signatureFile(sSignatureFile, true);
|
||||
if (signatureFile.MaxRetrievable() != pub.SignatureLength())
|
||||
return false;
|
||||
SecByteBlock signature(pub.SignatureLength());
|
||||
signatureFile.Get(signature, signature.size());
|
||||
|
||||
VerifierFilter *verifierFilter = new VerifierFilter(pub);
|
||||
verifierFilter->Put(signature, pub.SignatureLength());
|
||||
RageFileSource f(sMessageFilename, true, verifierFilter);
|
||||
|
||||
return verifierFilter->GetLastResult();
|
||||
}
|
||||
|
||||
bool CryptManager::Verify( CString sPath, CString sSignature )
|
||||
{
|
||||
if( !IsAFile(sPath) )
|
||||
return false;
|
||||
|
||||
ASSERT( PREFSMAN->m_bSignProfileData );
|
||||
|
||||
CString sPubFilename = PUBLIC_KEY_PATH;
|
||||
@@ -161,61 +140,43 @@ bool CryptManager::Verify( CString sPath, CString sSignature )
|
||||
if( !IsAFile(sPubFilename) )
|
||||
return false;
|
||||
|
||||
CString data;
|
||||
{
|
||||
RageFile in;
|
||||
if( !in.Open( sPath, RageFile::READ ) )
|
||||
RageException::Throw( "Error opening %s: %s", sPath.c_str(), in.GetError().c_str() );
|
||||
in.Read( data );
|
||||
}
|
||||
// CAREFUL: These classes can throw all kinds of exceptions. Should this
|
||||
// be wrapped in a try catch?
|
||||
|
||||
RSAKey key;
|
||||
{
|
||||
RageFile keyfile;
|
||||
if( !keyfile.Open( PRIVATE_KEY_PATH ) )
|
||||
RageException::Throw( "Error opening %s: %s", PRIVATE_KEY_PATH.c_str(), keyfile.GetError().c_str() );
|
||||
CString private_blob;
|
||||
keyfile.Read( private_blob );
|
||||
key.LoadFromPrivateBlob( private_blob );
|
||||
}
|
||||
RageFileSource pubFile(sPubFilename, true);
|
||||
RSASSA_PKCS1v15_SHA_Verifier pub(pubFile);
|
||||
|
||||
return key.Verify( data, sSignature );
|
||||
StringSource signatureFile(sSignature, true);
|
||||
if (signatureFile.MaxRetrievable() != pub.SignatureLength())
|
||||
return false;
|
||||
SecByteBlock signature(pub.SignatureLength());
|
||||
signatureFile.Get(signature, signature.size());
|
||||
|
||||
VerifierFilter *verifierFilter = new VerifierFilter(pub);
|
||||
verifierFilter->Put(signature, pub.SignatureLength());
|
||||
RageFileSource f(sMessageFilename, true, verifierFilter);
|
||||
|
||||
return verifierFilter->GetLastResult();
|
||||
}
|
||||
|
||||
CString BinaryToHex( const unsigned char *string, int iNumBytes )
|
||||
{
|
||||
CString s;
|
||||
for( int i=0; i<iNumBytes; i++ )
|
||||
{
|
||||
unsigned val = string[i];
|
||||
s += ssprintf( "%x", val );
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
CString CryptManager::GetMD5( CString fn )
|
||||
{
|
||||
struct MD5Context md5c;
|
||||
unsigned char digest[16];
|
||||
int iBytesRead;
|
||||
unsigned char buffer[1024];
|
||||
ASSERT( PREFSMAN->m_bSignProfileData );
|
||||
|
||||
RageFile file;
|
||||
if( !file.Open( fn, RageFile::READ ) )
|
||||
{
|
||||
LOG->Warn( "GetMD5: Failed to open file '%s'", fn.c_str() );
|
||||
return "";
|
||||
}
|
||||
MD5 md5;
|
||||
HashFilter md5Filter(md5);
|
||||
|
||||
MD5Init(&md5c);
|
||||
while( !file.AtEOF() && file.GetError().empty() )
|
||||
{
|
||||
iBytesRead = file.Read( buffer, sizeof(buffer) );
|
||||
MD5Update(&md5c, buffer, iBytesRead);
|
||||
}
|
||||
MD5Final(digest, &md5c);
|
||||
auto_ptr<ChannelSwitch> channelSwitch(new ChannelSwitch);
|
||||
channelSwitch->AddDefaultRoute(md5Filter);
|
||||
RageFileSource(fn, true, channelSwitch.release());
|
||||
|
||||
return BinaryToHex( digest, sizeof(digest) );
|
||||
HexEncoder encoder(new RageFileSink("temp.txt"), false);
|
||||
cout << "\nMD5: ";
|
||||
md5Filter.TransferTo(encoder);
|
||||
|
||||
ASSERT(0);
|
||||
return "";
|
||||
}
|
||||
|
||||
CString CryptManager::GetPublicKeyFileName()
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,76 @@
|
||||
# can't use -fno-rtti yet because it causes problems with exception handling in GCC 2.95.2
|
||||
CXXFLAGS = -g
|
||||
# Uncomment the next two lines to do a release build.
|
||||
# Note that you must define NDEBUG for your own application if you define it for Crypto++.
|
||||
# Also, make sure you run the validation tests and test your own program thoroughly
|
||||
# after turning on -O2. The GCC optimizer may have bugs that cause it to generate incorrect code.
|
||||
# CXXFLAGS = -O2 -DNDEBUG -ffunction-sections -fdata-sections
|
||||
# LDFLAGS = -Wl,--gc-sections
|
||||
ARFLAGS = -cr # ar needs the dash on OpenBSD
|
||||
RANLIB = ranlib
|
||||
UNAME = $(shell uname)
|
||||
|
||||
ifeq ($(UNAME),) # for DJGPP, where uname doesn't exist
|
||||
CXXFLAGS += -mbnu210
|
||||
else
|
||||
CXXFLAGS += -pipe
|
||||
endif
|
||||
|
||||
ifeq ($(UNAME),Darwin)
|
||||
AR = libtool
|
||||
ARFLAGS = -static -o
|
||||
CXXFLAGS += -D__pic__
|
||||
IS_GCC2 = $(shell c++ -v 2>&1 | grep -c gcc-932)
|
||||
ifeq ($(IS_GCC2),1)
|
||||
CXXFLAGS += -fno-coalesce-templates -fno-coalesce-static-vtables
|
||||
CXX = c++
|
||||
LDLIBS += -lstdc++
|
||||
LDFLAGS += -flat_namespace -undefined suppress -m
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(UNAME),SunOS)
|
||||
LDLIBS += -lnsl -lsocket
|
||||
endif
|
||||
|
||||
ifeq ($(CXX),gcc) # for some reason CXX is gcc on cygwin 1.1.4
|
||||
CXX = g++
|
||||
endif
|
||||
|
||||
SRCS = $(wildcard *.cpp)
|
||||
ifeq ($(SRCS),) # workaround wildcard function bug in GNU Make 3.77
|
||||
SRCS = $(shell ls *.cpp)
|
||||
endif
|
||||
|
||||
OBJS = $(SRCS:.cpp=.o)
|
||||
# test.o needs to be after bench.o for cygwin 1.1.4 (possible ld bug?)
|
||||
TESTOBJS = test.o
|
||||
#TESTOBJS = bench.o test.o validat1.o validat2.o validat3.o adhoc.o datatest.o regtest.o
|
||||
LIBOBJS = $(filter-out $(TESTOBJS),$(OBJS))
|
||||
|
||||
all: cryptest.exe
|
||||
|
||||
clean:
|
||||
$(RM) cryptest.exe libcryptopp.a $(LIBOBJS) $(TESTOBJS)
|
||||
|
||||
libcryptopp.a: $(LIBOBJS)
|
||||
$(AR) $(ARFLAGS) $@ $(LIBOBJS)
|
||||
$(RANLIB) $@
|
||||
|
||||
cryptest.exe: libcryptopp.a $(TESTOBJS)
|
||||
$(CXX) -o $@ $(CXXFLAGS) $(TESTOBJS) -L. -lcryptopp $(LDFLAGS) $(LDLIBS)
|
||||
|
||||
nolib: $(OBJS) # makes it faster to test changes
|
||||
$(CXX) -o ct $(CXXFLAGS) $(OBJS) $(LDFLAGS) $(LDLIBS)
|
||||
|
||||
adhoc.cpp: adhoc.cpp.proto
|
||||
ifeq ($(wildcard adhoc.cpp),)
|
||||
cp adhoc.cpp.proto adhoc.cpp
|
||||
else
|
||||
touch adhoc.cpp
|
||||
endif
|
||||
|
||||
.SUFFIXES: .cpp
|
||||
|
||||
.cpp.o:
|
||||
$(CXX) $(CXXFLAGS) -c $<
|
||||
@@ -0,0 +1,67 @@
|
||||
Compilation Copyright (c) 1995-2003 by Wei Dai. All rights reserved.
|
||||
This copyright applies only to this software distribution package
|
||||
as a compilation, and does not imply a copyright on any particular
|
||||
file in the package.
|
||||
|
||||
The following files are copyrighted by their respective original authors,
|
||||
and their use is subject to additional licenses included in these files.
|
||||
|
||||
mars.cpp - Copyright 1998 Brian Gladman.
|
||||
|
||||
All other files in this compilation are placed in the public domain by
|
||||
Wei Dai and other contributors.
|
||||
|
||||
I would like to thank the following authors for placing their works into
|
||||
the public domain:
|
||||
|
||||
Joan Daemen - 3way.cpp
|
||||
Leonard Janke - cast.cpp, seal.cpp
|
||||
Steve Reid - cast.cpp
|
||||
Phil Karn - des.cpp
|
||||
Michael Paul Johnson - diamond.cpp
|
||||
Andrew M. Kuchling - md2.cpp, md4.cpp
|
||||
Colin Plumb - md5.cpp, md5mac.cpp
|
||||
Seal Woods - rc6.cpp
|
||||
Chris Morgan - rijndael.cpp
|
||||
Paulo Baretto - rijndael.cpp, skipjack.cpp, square.cpp
|
||||
Richard De Moliner - safer.cpp
|
||||
Matthew Skala - twofish.cpp
|
||||
|
||||
Permission to use, copy, modify, and distribute this compilation for
|
||||
any purpose, including commercial applications, is hereby granted
|
||||
without fee, subject to the following restrictions:
|
||||
|
||||
1. Any copy or modification of this compilation in any form, except
|
||||
in object code form as part of an application software, must include
|
||||
the above copyright notice and this license.
|
||||
|
||||
2. Users of this software agree that any modification or extension
|
||||
they provide to Wei Dai will be considered public domain and not
|
||||
copyrighted unless it includes an explicit copyright notice.
|
||||
|
||||
3. Wei Dai makes no warranty or representation that the operation of the
|
||||
software in this compilation will be error-free, and Wei Dai is under no
|
||||
obligation to provide any services, by way of maintenance, update, or
|
||||
otherwise. THE SOFTWARE AND ANY DOCUMENTATION ARE PROVIDED "AS IS"
|
||||
WITHOUT EXPRESS OR IMPLIED WARRANTY INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. IN NO EVENT WILL WEI DAI OR ANY OTHER CONTRIBUTOR BE LIABLE FOR
|
||||
DIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
4. Users will not use Wei Dai or any other contributor's name in any
|
||||
publicity or advertising, without prior written consent in each case.
|
||||
|
||||
5. Export of this software from the United States may require a
|
||||
specific license from the United States Government. It is the
|
||||
responsibility of any person or organization contemplating export
|
||||
to obtain such a license before exporting.
|
||||
|
||||
6. Certain parts of this software may be protected by patents. It
|
||||
is the users' responsibility to obtain the appropriate
|
||||
licenses before using those parts.
|
||||
|
||||
If this compilation is used in object code form in an application
|
||||
software, acknowledgement of the author is not required but would be
|
||||
appreciated. The contribution of any useful modifications or extensions
|
||||
to Wei Dai is not required but would also be appreciated.
|
||||
@@ -0,0 +1,255 @@
|
||||
Crypto++: a C++ Class Library of Cryptographic Primitives
|
||||
Version 5.1 3/20/2003
|
||||
|
||||
This library includes:
|
||||
|
||||
- a class hierarchy with an API defined by abstract base classes
|
||||
- Proposed AES (Rijndael) and other AES candidates: RC6, MARS, Twofish,
|
||||
Serpent, CAST-256
|
||||
- other symmetric block ciphers: IDEA, DES, Triple DES (DES-EDE2 and
|
||||
DES-EDE3), DESX (DES-XEX3), RC2, RC5, Blowfish, Diamond2, TEA, SAFER,
|
||||
3-WAY, GOST, SHARK, CAST-128, Square, Skipjack
|
||||
- generic block cipher modes: ECB, CBC, CBC ciphertext stealing (CTS),
|
||||
CFB, OFB, counter (CTR) mode
|
||||
- stream ciphers: Panama, ARC4, SEAL, WAKE, WAKE-OFB, BlumBlumShub
|
||||
- public key cryptography: RSA, DSA, ElGamal, Nyberg-Rueppel (NR), Rabin,
|
||||
Rabin-Williams (RW), LUC, LUCELG, DLIES (variants of DHAES), ESIGN
|
||||
- padding schemes for public-key systems: PKCS#1 v2.0, OAEP, PSSR, IEEE
|
||||
P1363 EMSA2
|
||||
- key agreement schemes: Diffie-Hellman (DH), Unified Diffie-Hellman
|
||||
(DH2), Menezes-Qu-Vanstone (MQV), LUCDIF, XTR-DH
|
||||
- elliptic curve cryptography: ECDSA, ECNR, ECIES, ECDH, ECMQV (with
|
||||
optional cofactor multiplication for ECIES, ECDHC, ECMQVC)
|
||||
- one-way hash functions: SHA-1, MD2, MD4, MD5, HAVAL, RIPEMD-160, Tiger,
|
||||
SHA-2 (SHA-256, SHA-384, and SHA-512), Panama
|
||||
- public and private key validation for asymmetric algorithms
|
||||
- message authentication codes: MD5-MAC, HMAC, XOR-MAC, CBC-MAC, DMAC
|
||||
- cipher constructions based on hash functions: Luby-Rackoff, MDC
|
||||
- pseudo random number generators (PRNG): ANSI X9.17 appendix C, PGP's
|
||||
RandPool
|
||||
- Shamir's secret sharing scheme and Rabin's information dispersal
|
||||
algorithm (IDA)
|
||||
- DEFLATE (RFC 1951) compression/decompression with gzip (RFC 1952) and
|
||||
zlib (RFC 1950) format support
|
||||
- fast multi-precision integer (bignum) and polynomial operations
|
||||
- finite field arithmetics, including GF(p) and GF(2^n)
|
||||
- prime number generation and verification
|
||||
- various miscellaneous modules such as base 64 coding and 32-bit CRC
|
||||
- class wrappers for these operating system features (optional):
|
||||
- high resolution timers on Windows, Unix, and MacOS
|
||||
- Berkeley and Windows style sockets
|
||||
- Windows named pipes
|
||||
- /dev/random and /dev/urandom on Linux and FreeBSD
|
||||
- Microsoft's CryptGenRandom on Windows
|
||||
- A high level interface for most of the above, using a filter/pipeline
|
||||
metaphor
|
||||
- benchmarks and validation testing
|
||||
|
||||
You are welcome to use it for any purpose without paying me, but see
|
||||
license.txt for the fine print.
|
||||
|
||||
This version of Crypto++ has been compiled successfully with MSVC 6.0
|
||||
and 7.0 on Windows XP, GCC 2.95.4 on FreeBSD 4.6, GCC 2.95.3 on
|
||||
Linux 2.4 and SunOS 5.8, GCC 3.2 on Cygwin 1.3.12, and Metrowerks
|
||||
CodeWarrior 8.2.
|
||||
|
||||
To compile Crypto++ with MSVC, open the "cryptest.dsw" workspace file
|
||||
and build the "cryptest" project. This will compile Crypto++ as a static
|
||||
library and also build the test driver. Run the test driver and make sure
|
||||
the validation suite passes. Then to use the library simply insert the
|
||||
"cryptlib.dsp" project file into your own application workspace as a
|
||||
dependent project. You should check the compiler options to make sure
|
||||
that the library and your application are using the same C++ run-time
|
||||
libraries and calling conventions.
|
||||
|
||||
A makefile is included for you to compile Crypto++ with GCC. Make sure
|
||||
you are using GNU Make and GNU ld. The make process will produce two files,
|
||||
libcryptopp.a and cryptest.exe. Run "cryptest.exe v" for the validation
|
||||
suite.
|
||||
|
||||
Crypto++ is documented through inline comments in header files, which are
|
||||
processed through Doxygen to produce an HTML reference manual. You can find
|
||||
a link to the manual from http://www.cryptopp.com. Also at that site is
|
||||
the Crypto++ FAQ, which you should browse through before attempting to
|
||||
use this library, because it will likely answer many of questions that
|
||||
may come up.
|
||||
|
||||
If you run into any problems, please try the Crypto++ mailing list.
|
||||
The subscription information and the list archive are available on
|
||||
http://www.cryptopp.com. You can also email me directly at
|
||||
[email protected], but you will probably get a faster response through
|
||||
the mailing list.
|
||||
|
||||
Finally, a couple of usage notes to keep in mind:
|
||||
|
||||
1. If a constructor for A takes a pointer to an object B (except primitive
|
||||
types such as int and char), then A owns B and will delete B at A's
|
||||
destruction. If a constructor for A takes a reference to an object B,
|
||||
then the caller retains ownership of B and should not destroy it until
|
||||
A no longer needs it.
|
||||
|
||||
2. Crypto++ is thread safe at the class level. This means you can use
|
||||
Crypto++ safely in a multithreaded application, but you must provide
|
||||
synchronization when multiple threads access a common Crypto++ object.
|
||||
|
||||
Wei Dai
|
||||
|
||||
History
|
||||
|
||||
1.0 - First public release. Withdrawn at the request of RSA DSI.
|
||||
- included Blowfish, BBS, DES, DH, Diamond, DSA, ElGamal, IDEA,
|
||||
MD5, RC4, RC5, RSA, SHA, WAKE, secret sharing, DEFLATE compression
|
||||
- had a serious bug in the RSA key generation code.
|
||||
|
||||
1.1 - Removed RSA, RC4, RC5
|
||||
- Disabled calls to RSAREF's non-public functions
|
||||
- Minor bugs fixed
|
||||
|
||||
2.0 - a completely new, faster multiprecision integer class
|
||||
- added MD5-MAC, HAVAL, 3-WAY, TEA, SAFER, LUC, Rabin, BlumGoldwasser,
|
||||
elliptic curve algorithms
|
||||
- added the Lucas strong probable primality test
|
||||
- ElGamal encryption and signature schemes modified to avoid weaknesses
|
||||
- Diamond changed to Diamond2 because of key schedule weakness
|
||||
- fixed bug in WAKE key setup
|
||||
- SHS class renamed to SHA
|
||||
- lots of miscellaneous optimizations
|
||||
|
||||
2.1 - added Tiger, HMAC, GOST, RIPE-MD160, LUCELG, LUCDIF, XOR-MAC,
|
||||
OAEP, PSSR, SHARK
|
||||
- added precomputation to DH, ElGamal, DSA, and elliptic curve algorithms
|
||||
- added back RC5 and a new RSA
|
||||
- optimizations in elliptic curves over GF(p)
|
||||
- changed Rabin to use OAEP and PSSR
|
||||
- changed many classes to allow copy constructors to work correctly
|
||||
- improved exception generation and handling
|
||||
|
||||
2.2 - added SEAL, CAST-128, Square
|
||||
- fixed bug in HAVAL (padding problem)
|
||||
- fixed bug in triple-DES (decryption order was reversed)
|
||||
- fixed bug in RC5 (couldn't handle key length not a multiple of 4)
|
||||
- changed HMAC to conform to RFC-2104 (which is not compatible
|
||||
with the original HMAC)
|
||||
- changed secret sharing and information dispersal to use GF(2^32)
|
||||
instead of GF(65521)
|
||||
- removed zero knowledge prover/verifier for graph isomorphism
|
||||
- removed several utility classes in favor of the C++ standard library
|
||||
|
||||
2.3 - ported to EGCS
|
||||
- fixed incomplete workaround of min/max conflict in MSVC
|
||||
|
||||
3.0 - placed all names into the "CryptoPP" namespace
|
||||
- added MD2, RC2, RC6, MARS, RW, DH2, MQV, ECDHC, CBC-CTS
|
||||
- added abstract base classes PK_SimpleKeyAgreementDomain and
|
||||
PK_AuthenticatedKeyAgreementDomain
|
||||
- changed DH and LUCDIF to implement the PK_SimpleKeyAgreementDomain
|
||||
interface and to perform domain parameter and key validation
|
||||
- changed interfaces of PK_Signer and PK_Verifier to sign and verify
|
||||
messages instead of message digests
|
||||
- changed OAEP to conform to PKCS#1 v2.0
|
||||
- changed benchmark code to produce HTML tables as output
|
||||
- changed PSSR to track IEEE P1363a
|
||||
- renamed ElGamalSignature to NR and changed it to track IEEE P1363
|
||||
- renamed ECKEP to ECMQVC and changed it to track IEEE P1363
|
||||
- renamed several other classes for clarity
|
||||
- removed support for calling RSAREF
|
||||
- removed option to compile old SHA (SHA-0)
|
||||
- removed option not to throw exceptions
|
||||
|
||||
3.1 - added ARC4, Rijndael, Twofish, Serpent, CBC-MAC, DMAC
|
||||
- added interface for querying supported key lengths of symmetric ciphers
|
||||
and MACs
|
||||
- added sample code for RSA signature and verification
|
||||
- changed CBC-CTS to be compatible with RFC 2040
|
||||
- updated SEAL to version 3.0 of the cipher specification
|
||||
- optimized multiprecision squaring and elliptic curves over GF(p)
|
||||
- fixed bug in MARS key setup
|
||||
- fixed bug with attaching objects to Deflator
|
||||
|
||||
3.2 - added DES-XEX3, ECDSA, DefaultEncryptorWithMAC
|
||||
- renamed DES-EDE to DES-EDE2 and TripleDES to DES-EDE3
|
||||
- optimized ARC4
|
||||
- generalized DSA to allow keys longer than 1024 bits
|
||||
- fixed bugs in GF2N and ModularArithmetic that can cause calculation errors
|
||||
- fixed crashing bug in Inflator when given invalid inputs
|
||||
- fixed endian bug in Serpent
|
||||
- fixed padding bug in Tiger
|
||||
|
||||
4.0 - added Skipjack, CAST-256, Panama, SHA-2 (SHA-256, SHA-384, and SHA-512),
|
||||
and XTR-DH
|
||||
- added a faster variant of Rabin's Information Dispersal Algorithm (IDA)
|
||||
- added class wrappers for these operating system features:
|
||||
- high resolution timers on Windows, Unix, and MacOS
|
||||
- Berkeley and Windows style sockets
|
||||
- Windows named pipes
|
||||
- /dev/random and /dev/urandom on Linux and FreeBSD
|
||||
- Microsoft's CryptGenRandom on Windows
|
||||
- added support for SEC 1 elliptic curve key format and compressed points
|
||||
- added support for X.509 public key format (subjectPublicKeyInfo) for
|
||||
RSA, DSA, and elliptic curve schemes
|
||||
- added support for DER and OpenPGP signature format for DSA
|
||||
- added support for ZLIB compressed data format (RFC 1950)
|
||||
- changed elliptic curve encryption to use ECIES (as defined in SEC 1)
|
||||
- changed MARS key schedule to reflect the latest specification
|
||||
- changed BufferedTransformation interface to support multiple channels
|
||||
and messages
|
||||
- changed CAST and SHA-1 implementations to use public domain source code
|
||||
- fixed bug in StringSource
|
||||
- optmized multi-precision integer code for better performance
|
||||
|
||||
4.1 - added more support for the recommended elliptic curve parameters in SEC 2
|
||||
- added Panama MAC, MARC4
|
||||
- added IV stealing feature to CTS mode
|
||||
- added support for PKCS #8 private key format for RSA, DSA, and elliptic
|
||||
curve schemes
|
||||
- changed Deflate, MD5, Rijndael, and Twofish to use public domain code
|
||||
- fixed a bug with flushing compressed streams
|
||||
- fixed a bug with decompressing stored blocks
|
||||
- fixed a bug with EC point decompression using non-trinomial basis
|
||||
- fixed a bug in NetworkSource::GeneralPump()
|
||||
- fixed a performance issue with EC over GF(p) decryption
|
||||
- fixed syntax to allow GCC to compile without -fpermissive
|
||||
- relaxed some restrictions in the license
|
||||
|
||||
4.2 - added support for longer HMAC keys
|
||||
- added MD4 (which is not secure so use for compatibility purposes only)
|
||||
- added compatibility fixes/workarounds for STLport 4.5, GCC 3.0.2,
|
||||
and MSVC 7.0
|
||||
- changed MD2 to use public domain code
|
||||
- fixed a bug with decompressing multiple messages with the same object
|
||||
- fixed a bug in CBC-MAC with MACing multiple messages with the same object
|
||||
- fixed a bug in RC5 and RC6 with zero-length keys
|
||||
- fixed a bug in Adler32 where incorrect checksum may be generated
|
||||
|
||||
5.0 - added ESIGN, DLIES, WAKE-OFB, PBKDF1 and PBKDF2 from PKCS #5
|
||||
- added key validation for encryption and signature public/private keys
|
||||
- renamed StreamCipher interface to SymmetricCipher, which is now implemented
|
||||
by both stream ciphers and block cipher modes including ECB and CBC
|
||||
- added keying interfaces to support resetting of keys and IVs without
|
||||
having to destroy and recreate objects
|
||||
- changed filter interface to support non-blocking input/output
|
||||
- changed SocketSource and SocketSink to use overlapped I/O on Microsoft Windows
|
||||
- grouped related classes inside structs to help templates, for example
|
||||
AESEncryption and AESDecryption are now AES::Encryption and AES::Decryption
|
||||
- where possible, typedefs have been added to improve backwards
|
||||
compatibility when the CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY macro is defined
|
||||
- changed Serpent, HAVAL and IDEA to use public domain code
|
||||
- implemented SSE2 optimizations for Integer operations
|
||||
- fixed a bug in HMAC::TruncatedFinal()
|
||||
- fixed SKIPJACK byte ordering following NIST clarification dated 5/9/02
|
||||
|
||||
5.01 (special FIPS 140-2 release, in development)
|
||||
- added known answer test for X9.17 RNG in FIPS 140 power-up self test
|
||||
- is being evaluated for FIPS 140-2 compliance
|
||||
|
||||
5.1 - added PSS padding and changed PSSR to track IEEE P1363a draft standard
|
||||
- added blinding for RSA and Rabin to defend against timing attacks
|
||||
on decryption operations
|
||||
- changed signing and decryption APIs to support the above
|
||||
- changed WaitObjectContainer to allow waiting for more than 64
|
||||
objects at a time on Win32 platforms
|
||||
- fixed a bug in CBC and ECB modes with processing non-aligned data
|
||||
- fixed standard conformance bugs in DLIES (DHAES mode) and RW/EMSA2
|
||||
signature scheme (these fixes are not backwards compatible)
|
||||
- fixed a number of compiler warnings, minor bugs, and portability problems
|
||||
- removed Sapphire
|
||||
Binary file not shown.
@@ -0,0 +1,340 @@
|
||||
// algebra.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
#include "algebra.h"
|
||||
#include "integer.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
template <class T> const T& AbstractGroup<T>::Double(const Element &a) const
|
||||
{
|
||||
return Add(a, a);
|
||||
}
|
||||
|
||||
template <class T> const T& AbstractGroup<T>::Subtract(const Element &a, const Element &b) const
|
||||
{
|
||||
// make copy of a in case Inverse() overwrites it
|
||||
Element a1(a);
|
||||
return Add(a1, Inverse(b));
|
||||
}
|
||||
|
||||
template <class T> T& AbstractGroup<T>::Accumulate(Element &a, const Element &b) const
|
||||
{
|
||||
return a = Add(a, b);
|
||||
}
|
||||
|
||||
template <class T> T& AbstractGroup<T>::Reduce(Element &a, const Element &b) const
|
||||
{
|
||||
return a = Subtract(a, b);
|
||||
}
|
||||
|
||||
template <class T> const T& AbstractRing<T>::Square(const Element &a) const
|
||||
{
|
||||
return Multiply(a, a);
|
||||
}
|
||||
|
||||
template <class T> const T& AbstractRing<T>::Divide(const Element &a, const Element &b) const
|
||||
{
|
||||
// make copy of a in case MultiplicativeInverse() overwrites it
|
||||
Element a1(a);
|
||||
return Multiply(a1, MultiplicativeInverse(b));
|
||||
}
|
||||
|
||||
template <class T> const T& AbstractEuclideanDomain<T>::Mod(const Element &a, const Element &b) const
|
||||
{
|
||||
Element q;
|
||||
DivisionAlgorithm(result, q, a, b);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T> const T& AbstractEuclideanDomain<T>::Gcd(const Element &a, const Element &b) const
|
||||
{
|
||||
Element g[3]={b, a};
|
||||
unsigned int i0=0, i1=1, i2=2;
|
||||
|
||||
while (!Equal(g[i1], Identity()))
|
||||
{
|
||||
g[i2] = Mod(g[i0], g[i1]);
|
||||
unsigned int t = i0; i0 = i1; i1 = i2; i2 = t;
|
||||
}
|
||||
|
||||
return result = g[i0];
|
||||
}
|
||||
|
||||
template <class T> const typename QuotientRing<T>::Element& QuotientRing<T>::MultiplicativeInverse(const Element &a) const
|
||||
{
|
||||
Element g[3]={m_modulus, a};
|
||||
#ifdef __BCPLUSPLUS__
|
||||
// BC++50 workaround
|
||||
Element v[3];
|
||||
v[0]=m_domain.Identity();
|
||||
v[1]=m_domain.MultiplicativeIdentity();
|
||||
#else
|
||||
Element v[3]={m_domain.Identity(), m_domain.MultiplicativeIdentity()};
|
||||
#endif
|
||||
Element y;
|
||||
unsigned int i0=0, i1=1, i2=2;
|
||||
|
||||
while (!Equal(g[i1], Identity()))
|
||||
{
|
||||
// y = g[i0] / g[i1];
|
||||
// g[i2] = g[i0] % g[i1];
|
||||
m_domain.DivisionAlgorithm(g[i2], y, g[i0], g[i1]);
|
||||
// v[i2] = v[i0] - (v[i1] * y);
|
||||
v[i2] = m_domain.Subtract(v[i0], m_domain.Multiply(v[i1], y));
|
||||
unsigned int t = i0; i0 = i1; i1 = i2; i2 = t;
|
||||
}
|
||||
|
||||
return m_domain.IsUnit(g[i0]) ? m_domain.Divide(v[i0], g[i0]) : m_domain.Identity();
|
||||
}
|
||||
|
||||
template <class T> T AbstractGroup<T>::ScalarMultiply(const Element &base, const Integer &exponent) const
|
||||
{
|
||||
Element result;
|
||||
SimultaneousMultiply(&result, base, &exponent, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T> T AbstractGroup<T>::CascadeScalarMultiply(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const
|
||||
{
|
||||
const unsigned expLen = STDMAX(e1.BitCount(), e2.BitCount());
|
||||
if (expLen==0)
|
||||
return Identity();
|
||||
|
||||
const unsigned w = (expLen <= 46 ? 1 : (expLen <= 260 ? 2 : 3));
|
||||
const unsigned tableSize = 1<<w;
|
||||
std::vector<Element> powerTable(tableSize << w);
|
||||
|
||||
powerTable[1] = x;
|
||||
powerTable[tableSize] = y;
|
||||
if (w==1)
|
||||
powerTable[3] = Add(x,y);
|
||||
else
|
||||
{
|
||||
powerTable[2] = Double(x);
|
||||
powerTable[2*tableSize] = Double(y);
|
||||
|
||||
unsigned i, j;
|
||||
|
||||
for (i=3; i<tableSize; i+=2)
|
||||
powerTable[i] = Add(powerTable[i-2], powerTable[2]);
|
||||
for (i=1; i<tableSize; i+=2)
|
||||
for (j=i+tableSize; j<(tableSize<<w); j+=tableSize)
|
||||
powerTable[j] = Add(powerTable[j-tableSize], y);
|
||||
|
||||
for (i=3*tableSize; i<(tableSize<<w); i+=2*tableSize)
|
||||
powerTable[i] = Add(powerTable[i-2*tableSize], powerTable[2*tableSize]);
|
||||
for (i=tableSize; i<(tableSize<<w); i+=2*tableSize)
|
||||
for (j=i+2; j<i+tableSize; j+=2)
|
||||
powerTable[j] = Add(powerTable[j-1], x);
|
||||
}
|
||||
|
||||
Element result;
|
||||
unsigned power1 = 0, power2 = 0, prevPosition = expLen-1;
|
||||
bool firstTime = true;
|
||||
|
||||
for (int i = expLen-1; i>=0; i--)
|
||||
{
|
||||
power1 = 2*power1 + e1.GetBit(i);
|
||||
power2 = 2*power2 + e2.GetBit(i);
|
||||
|
||||
if (i==0 || 2*power1 >= tableSize || 2*power2 >= tableSize)
|
||||
{
|
||||
unsigned squaresBefore = prevPosition-i;
|
||||
unsigned squaresAfter = 0;
|
||||
prevPosition = i;
|
||||
while ((power1 || power2) && power1%2 == 0 && power2%2==0)
|
||||
{
|
||||
power1 /= 2;
|
||||
power2 /= 2;
|
||||
squaresBefore--;
|
||||
squaresAfter++;
|
||||
}
|
||||
if (firstTime)
|
||||
{
|
||||
result = powerTable[(power2<<w) + power1];
|
||||
firstTime = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (squaresBefore--)
|
||||
result = Double(result);
|
||||
if (power1 || power2)
|
||||
Accumulate(result, powerTable[(power2<<w) + power1]);
|
||||
}
|
||||
while (squaresAfter--)
|
||||
result = Double(result);
|
||||
power1 = power2 = 0;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class Element, class Iterator> Element GeneralCascadeMultiplication(const AbstractGroup<Element> &group, Iterator begin, Iterator end)
|
||||
{
|
||||
if (end-begin == 1)
|
||||
return group.ScalarMultiply(begin->base, begin->exponent);
|
||||
else if (end-begin == 2)
|
||||
return group.CascadeScalarMultiply(begin->base, begin->exponent, (begin+1)->base, (begin+1)->exponent);
|
||||
else
|
||||
{
|
||||
Integer q, t;
|
||||
Iterator last = end;
|
||||
--last;
|
||||
|
||||
std::make_heap(begin, end);
|
||||
std::pop_heap(begin, end);
|
||||
|
||||
while (!!begin->exponent)
|
||||
{
|
||||
// last->exponent is largest exponent, begin->exponent is next largest
|
||||
t = last->exponent;
|
||||
Integer::Divide(last->exponent, q, t, begin->exponent);
|
||||
|
||||
if (q == Integer::One())
|
||||
group.Accumulate(begin->base, last->base); // avoid overhead of ScalarMultiply()
|
||||
else
|
||||
group.Accumulate(begin->base, group.ScalarMultiply(last->base, q));
|
||||
|
||||
std::push_heap(begin, end);
|
||||
std::pop_heap(begin, end);
|
||||
}
|
||||
|
||||
return group.ScalarMultiply(last->base, last->exponent);
|
||||
}
|
||||
}
|
||||
|
||||
struct WindowSlider
|
||||
{
|
||||
WindowSlider(const Integer &exp, bool fastNegate, unsigned int windowSizeIn=0)
|
||||
: exp(exp), windowModulus(Integer::One()), windowSize(windowSizeIn), windowBegin(0), fastNegate(fastNegate), firstTime(true), finished(false)
|
||||
{
|
||||
if (windowSize == 0)
|
||||
{
|
||||
unsigned int expLen = exp.BitCount();
|
||||
windowSize = expLen <= 17 ? 1 : (expLen <= 24 ? 2 : (expLen <= 70 ? 3 : (expLen <= 197 ? 4 : (expLen <= 539 ? 5 : (expLen <= 1434 ? 6 : 7)))));
|
||||
}
|
||||
windowModulus <<= windowSize;
|
||||
}
|
||||
|
||||
void FindNextWindow()
|
||||
{
|
||||
unsigned int expLen = exp.WordCount() * WORD_BITS;
|
||||
unsigned int skipCount = firstTime ? 0 : windowSize;
|
||||
firstTime = false;
|
||||
while (!exp.GetBit(skipCount))
|
||||
{
|
||||
if (skipCount >= expLen)
|
||||
{
|
||||
finished = true;
|
||||
return;
|
||||
}
|
||||
skipCount++;
|
||||
}
|
||||
|
||||
exp >>= skipCount;
|
||||
windowBegin += skipCount;
|
||||
expWindow = exp % (1 << windowSize);
|
||||
|
||||
if (fastNegate && exp.GetBit(windowSize))
|
||||
{
|
||||
negateNext = true;
|
||||
expWindow = (1 << windowSize) - expWindow;
|
||||
exp += windowModulus;
|
||||
}
|
||||
else
|
||||
negateNext = false;
|
||||
}
|
||||
|
||||
Integer exp, windowModulus;
|
||||
unsigned int windowSize, windowBegin, expWindow;
|
||||
bool fastNegate, negateNext, firstTime, finished;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
void AbstractGroup<T>::SimultaneousMultiply(T *results, const T &base, const Integer *expBegin, unsigned int expCount) const
|
||||
{
|
||||
std::vector<std::vector<Element> > buckets(expCount);
|
||||
std::vector<WindowSlider> exponents;
|
||||
exponents.reserve(expCount);
|
||||
unsigned int i;
|
||||
|
||||
for (i=0; i<expCount; i++)
|
||||
{
|
||||
assert(expBegin->NotNegative());
|
||||
exponents.push_back(WindowSlider(*expBegin++, InversionIsFast(), 0));
|
||||
exponents[i].FindNextWindow();
|
||||
buckets[i].resize(1<<(exponents[i].windowSize-1), Identity());
|
||||
}
|
||||
|
||||
unsigned int expBitPosition = 0;
|
||||
Element g = base;
|
||||
bool notDone = true;
|
||||
|
||||
while (notDone)
|
||||
{
|
||||
notDone = false;
|
||||
for (i=0; i<expCount; i++)
|
||||
{
|
||||
if (!exponents[i].finished && expBitPosition == exponents[i].windowBegin)
|
||||
{
|
||||
Element &bucket = buckets[i][exponents[i].expWindow/2];
|
||||
if (exponents[i].negateNext)
|
||||
Accumulate(bucket, Inverse(g));
|
||||
else
|
||||
Accumulate(bucket, g);
|
||||
exponents[i].FindNextWindow();
|
||||
}
|
||||
notDone = notDone || !exponents[i].finished;
|
||||
}
|
||||
|
||||
if (notDone)
|
||||
{
|
||||
g = Double(g);
|
||||
expBitPosition++;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i<expCount; i++)
|
||||
{
|
||||
Element &r = *results++;
|
||||
r = buckets[i][buckets[i].size()-1];
|
||||
if (buckets[i].size() > 1)
|
||||
{
|
||||
for (int j = buckets[i].size()-2; j >= 1; j--)
|
||||
{
|
||||
Accumulate(buckets[i][j], buckets[i][j+1]);
|
||||
Accumulate(r, buckets[i][j]);
|
||||
}
|
||||
Accumulate(buckets[i][0], buckets[i][1]);
|
||||
r = Add(Double(r), buckets[i][0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class T> T AbstractRing<T>::Exponentiate(const Element &base, const Integer &exponent) const
|
||||
{
|
||||
Element result;
|
||||
SimultaneousExponentiate(&result, base, &exponent, 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T> T AbstractRing<T>::CascadeExponentiate(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const
|
||||
{
|
||||
return MultiplicativeGroup().AbstractGroup<T>::CascadeScalarMultiply(x, e1, y, e2);
|
||||
}
|
||||
|
||||
template <class Element, class Iterator> Element GeneralCascadeExponentiation(const AbstractRing<Element> &ring, Iterator begin, Iterator end)
|
||||
{
|
||||
return GeneralCascadeMultiplication<Element>(ring.MultiplicativeGroup(), begin, end);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void AbstractRing<T>::SimultaneousExponentiate(T *results, const T &base, const Integer *exponents, unsigned int expCount) const
|
||||
{
|
||||
MultiplicativeGroup().AbstractGroup<T>::SimultaneousMultiply(results, base, exponents, expCount);
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -0,0 +1,275 @@
|
||||
#ifndef CRYPTOPP_ALGEBRA_H
|
||||
#define CRYPTOPP_ALGEBRA_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
class Integer;
|
||||
|
||||
// "const Element&" returned by member functions are references
|
||||
// to internal data members. Since each object may have only
|
||||
// one such data member for holding results, the following code
|
||||
// will produce incorrect results:
|
||||
// abcd = group.Add(group.Add(a,b), group.Add(c,d));
|
||||
// But this should be fine:
|
||||
// abcd = group.Add(a, group.Add(b, group.Add(c,d));
|
||||
|
||||
//! Abstract Group
|
||||
template <class T> class AbstractGroup
|
||||
{
|
||||
public:
|
||||
typedef T Element;
|
||||
|
||||
virtual ~AbstractGroup() {}
|
||||
|
||||
virtual bool Equal(const Element &a, const Element &b) const =0;
|
||||
virtual const Element& Identity() const =0;
|
||||
virtual const Element& Add(const Element &a, const Element &b) const =0;
|
||||
virtual const Element& Inverse(const Element &a) const =0;
|
||||
virtual bool InversionIsFast() const {return false;}
|
||||
|
||||
virtual const Element& Double(const Element &a) const;
|
||||
virtual const Element& Subtract(const Element &a, const Element &b) const;
|
||||
virtual Element& Accumulate(Element &a, const Element &b) const;
|
||||
virtual Element& Reduce(Element &a, const Element &b) const;
|
||||
|
||||
virtual Element ScalarMultiply(const Element &a, const Integer &e) const;
|
||||
virtual Element CascadeScalarMultiply(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const;
|
||||
|
||||
virtual void SimultaneousMultiply(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const;
|
||||
};
|
||||
|
||||
//! Abstract Ring
|
||||
template <class T> class AbstractRing : public AbstractGroup<T>
|
||||
{
|
||||
public:
|
||||
typedef T Element;
|
||||
|
||||
AbstractRing() {m_mg.m_pRing = this;}
|
||||
AbstractRing(const AbstractRing &source) {m_mg.m_pRing = this;}
|
||||
AbstractRing& operator=(const AbstractRing &source) {return *this;}
|
||||
|
||||
virtual bool IsUnit(const Element &a) const =0;
|
||||
virtual const Element& MultiplicativeIdentity() const =0;
|
||||
virtual const Element& Multiply(const Element &a, const Element &b) const =0;
|
||||
virtual const Element& MultiplicativeInverse(const Element &a) const =0;
|
||||
|
||||
virtual const Element& Square(const Element &a) const;
|
||||
virtual const Element& Divide(const Element &a, const Element &b) const;
|
||||
|
||||
virtual Element Exponentiate(const Element &a, const Integer &e) const;
|
||||
virtual Element CascadeExponentiate(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const;
|
||||
|
||||
virtual void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const;
|
||||
|
||||
virtual const AbstractGroup<T>& MultiplicativeGroup() const
|
||||
{return m_mg;}
|
||||
|
||||
private:
|
||||
class MultiplicativeGroupT : public AbstractGroup<T>
|
||||
{
|
||||
public:
|
||||
const AbstractRing<T>& GetRing() const
|
||||
{return *m_pRing;}
|
||||
|
||||
bool Equal(const Element &a, const Element &b) const
|
||||
{return GetRing().Equal(a, b);}
|
||||
|
||||
const Element& Identity() const
|
||||
{return GetRing().MultiplicativeIdentity();}
|
||||
|
||||
const Element& Add(const Element &a, const Element &b) const
|
||||
{return GetRing().Multiply(a, b);}
|
||||
|
||||
Element& Accumulate(Element &a, const Element &b) const
|
||||
{return a = GetRing().Multiply(a, b);}
|
||||
|
||||
const Element& Inverse(const Element &a) const
|
||||
{return GetRing().MultiplicativeInverse(a);}
|
||||
|
||||
const Element& Subtract(const Element &a, const Element &b) const
|
||||
{return GetRing().Divide(a, b);}
|
||||
|
||||
Element& Reduce(Element &a, const Element &b) const
|
||||
{return a = GetRing().Divide(a, b);}
|
||||
|
||||
const Element& Double(const Element &a) const
|
||||
{return GetRing().Square(a);}
|
||||
|
||||
Element ScalarMultiply(const Element &a, const Integer &e) const
|
||||
{return GetRing().Exponentiate(a, e);}
|
||||
|
||||
Element CascadeScalarMultiply(const Element &x, const Integer &e1, const Element &y, const Integer &e2) const
|
||||
{return GetRing().CascadeExponentiate(x, e1, y, e2);}
|
||||
|
||||
void SimultaneousMultiply(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const
|
||||
{GetRing().SimultaneousExponentiate(results, base, exponents, exponentsCount);}
|
||||
|
||||
const AbstractRing<T> *m_pRing;
|
||||
};
|
||||
|
||||
MultiplicativeGroupT m_mg;
|
||||
};
|
||||
|
||||
// ********************************************************
|
||||
|
||||
//! Base and Exponent
|
||||
template <class T, class E = Integer>
|
||||
struct BaseAndExponent
|
||||
{
|
||||
public:
|
||||
BaseAndExponent() {}
|
||||
BaseAndExponent(const T &base, const E &exponent) : base(base), exponent(exponent) {}
|
||||
bool operator<(const BaseAndExponent<T, E> &rhs) const {return exponent < rhs.exponent;}
|
||||
T base;
|
||||
E exponent;
|
||||
};
|
||||
|
||||
// VC60 workaround: incomplete member template support
|
||||
template <class Element, class Iterator>
|
||||
Element GeneralCascadeMultiplication(const AbstractGroup<Element> &group, Iterator begin, Iterator end);
|
||||
template <class Element, class Iterator>
|
||||
Element GeneralCascadeExponentiation(const AbstractRing<Element> &ring, Iterator begin, Iterator end);
|
||||
|
||||
// ********************************************************
|
||||
|
||||
//! Abstract Euclidean Domain
|
||||
template <class T> class AbstractEuclideanDomain : public AbstractRing<T>
|
||||
{
|
||||
public:
|
||||
typedef T Element;
|
||||
|
||||
virtual void DivisionAlgorithm(Element &r, Element &q, const Element &a, const Element &d) const =0;
|
||||
|
||||
virtual const Element& Mod(const Element &a, const Element &b) const =0;
|
||||
virtual const Element& Gcd(const Element &a, const Element &b) const;
|
||||
|
||||
protected:
|
||||
mutable Element result;
|
||||
};
|
||||
|
||||
// ********************************************************
|
||||
|
||||
//! EuclideanDomainOf
|
||||
template <class T> class EuclideanDomainOf : public AbstractEuclideanDomain<T>
|
||||
{
|
||||
public:
|
||||
typedef T Element;
|
||||
|
||||
EuclideanDomainOf() {}
|
||||
|
||||
bool Equal(const Element &a, const Element &b) const
|
||||
{return a==b;}
|
||||
|
||||
const Element& Identity() const
|
||||
{return Element::Zero();}
|
||||
|
||||
const Element& Add(const Element &a, const Element &b) const
|
||||
{return result = a+b;}
|
||||
|
||||
Element& Accumulate(Element &a, const Element &b) const
|
||||
{return a+=b;}
|
||||
|
||||
const Element& Inverse(const Element &a) const
|
||||
{return result = -a;}
|
||||
|
||||
const Element& Subtract(const Element &a, const Element &b) const
|
||||
{return result = a-b;}
|
||||
|
||||
Element& Reduce(Element &a, const Element &b) const
|
||||
{return a-=b;}
|
||||
|
||||
const Element& Double(const Element &a) const
|
||||
{return result = a.Doubled();}
|
||||
|
||||
const Element& MultiplicativeIdentity() const
|
||||
{return Element::One();}
|
||||
|
||||
const Element& Multiply(const Element &a, const Element &b) const
|
||||
{return result = a*b;}
|
||||
|
||||
const Element& Square(const Element &a) const
|
||||
{return result = a.Squared();}
|
||||
|
||||
bool IsUnit(const Element &a) const
|
||||
{return a.IsUnit();}
|
||||
|
||||
const Element& MultiplicativeInverse(const Element &a) const
|
||||
{return result = a.MultiplicativeInverse();}
|
||||
|
||||
const Element& Divide(const Element &a, const Element &b) const
|
||||
{return result = a/b;}
|
||||
|
||||
const Element& Mod(const Element &a, const Element &b) const
|
||||
{return result = a%b;}
|
||||
|
||||
void DivisionAlgorithm(Element &r, Element &q, const Element &a, const Element &d) const
|
||||
{Element::Divide(r, q, a, d);}
|
||||
|
||||
private:
|
||||
mutable Element result;
|
||||
};
|
||||
|
||||
//! Quotient Ring
|
||||
template <class T> class QuotientRing : public AbstractRing<typename T::Element>
|
||||
{
|
||||
public:
|
||||
typedef T EuclideanDomain;
|
||||
typedef typename T::Element Element;
|
||||
|
||||
QuotientRing(const EuclideanDomain &domain, const Element &modulus)
|
||||
: m_domain(domain), m_modulus(modulus) {}
|
||||
|
||||
const EuclideanDomain & GetDomain() const
|
||||
{return m_domain;}
|
||||
|
||||
const Element& GetModulus() const
|
||||
{return m_modulus;}
|
||||
|
||||
bool Equal(const Element &a, const Element &b) const
|
||||
{return m_domain.Equal(m_domain.Mod(m_domain.Subtract(a, b), m_modulus), m_domain.Identity());}
|
||||
|
||||
const Element& Identity() const
|
||||
{return m_domain.Identity();}
|
||||
|
||||
const Element& Add(const Element &a, const Element &b) const
|
||||
{return m_domain.Add(a, b);}
|
||||
|
||||
Element& Accumulate(Element &a, const Element &b) const
|
||||
{return m_domain.Accumulate(a, b);}
|
||||
|
||||
const Element& Inverse(const Element &a) const
|
||||
{return m_domain.Inverse(a);}
|
||||
|
||||
const Element& Subtract(const Element &a, const Element &b) const
|
||||
{return m_domain.Subtract(a, b);}
|
||||
|
||||
Element& Reduce(Element &a, const Element &b) const
|
||||
{return m_domain.Reduce(a, b);}
|
||||
|
||||
const Element& Double(const Element &a) const
|
||||
{return m_domain.Double(a);}
|
||||
|
||||
bool IsUnit(const Element &a) const
|
||||
{return m_domain.IsUnit(m_domain.Gcd(a, m_modulus));}
|
||||
|
||||
const Element& MultiplicativeIdentity() const
|
||||
{return m_domain.MultiplicativeIdentity();}
|
||||
|
||||
const Element& Multiply(const Element &a, const Element &b) const
|
||||
{return m_domain.Mod(m_domain.Multiply(a, b), m_modulus);}
|
||||
|
||||
const Element& Square(const Element &a) const
|
||||
{return m_domain.Mod(m_domain.Square(a), m_modulus);}
|
||||
|
||||
const Element& MultiplicativeInverse(const Element &a) const;
|
||||
|
||||
protected:
|
||||
EuclideanDomain m_domain;
|
||||
Element m_modulus;
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,10 @@
|
||||
// algparam.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
#include "algparam.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
bool (*AssignIntToInteger)(const std::type_info &valueType, void *pInteger, const void *pInt) = NULL;
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -0,0 +1,325 @@
|
||||
#ifndef CRYPTOPP_ALGPARAM_H
|
||||
#define CRYPTOPP_ALGPARAM_H
|
||||
|
||||
#include "cryptlib.h"
|
||||
#include "smartptr.h"
|
||||
#include "secblock.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
//! used to pass byte array input as part of a NameValuePairs object
|
||||
/*! the deepCopy option is used when the NameValuePairs object can't
|
||||
keep a copy of the data available */
|
||||
class ConstByteArrayParameter
|
||||
{
|
||||
public:
|
||||
ConstByteArrayParameter(const char *data = NULL, bool deepCopy = false)
|
||||
{
|
||||
Assign((const byte *)data, data ? strlen(data) : 0, deepCopy);
|
||||
}
|
||||
ConstByteArrayParameter(const byte *data, unsigned int size, bool deepCopy = false)
|
||||
{
|
||||
Assign(data, size, deepCopy);
|
||||
}
|
||||
template <class T> ConstByteArrayParameter(const T &string, bool deepCopy = false)
|
||||
{
|
||||
CRYPTOPP_COMPILE_ASSERT(sizeof(string[0])==1);
|
||||
Assign((const byte *)string.data(), string.size(), deepCopy);
|
||||
}
|
||||
|
||||
void Assign(const byte *data, unsigned int size, bool deepCopy)
|
||||
{
|
||||
if (deepCopy)
|
||||
m_block.Assign(data, size);
|
||||
else
|
||||
{
|
||||
m_data = data;
|
||||
m_size = size;
|
||||
}
|
||||
m_deepCopy = deepCopy;
|
||||
}
|
||||
|
||||
const byte *begin() const {return m_deepCopy ? m_block.begin() : m_data;}
|
||||
const byte *end() const {return m_deepCopy ? m_block.end() : m_data + m_size;}
|
||||
unsigned int size() const {return m_deepCopy ? m_block.size() : m_size;}
|
||||
|
||||
private:
|
||||
bool m_deepCopy;
|
||||
const byte *m_data;
|
||||
unsigned int m_size;
|
||||
SecByteBlock m_block;
|
||||
};
|
||||
|
||||
class ByteArrayParameter
|
||||
{
|
||||
public:
|
||||
ByteArrayParameter(byte *data = NULL, unsigned int size = 0)
|
||||
: m_data(data), m_size(size) {}
|
||||
ByteArrayParameter(SecByteBlock &block)
|
||||
: m_data(block.begin()), m_size(block.size()) {}
|
||||
|
||||
byte *begin() const {return m_data;}
|
||||
byte *end() const {return m_data + m_size;}
|
||||
unsigned int size() const {return m_size;}
|
||||
|
||||
private:
|
||||
byte *m_data;
|
||||
unsigned int m_size;
|
||||
};
|
||||
|
||||
class CombinedNameValuePairs : public NameValuePairs
|
||||
{
|
||||
public:
|
||||
CombinedNameValuePairs(const NameValuePairs &pairs1, const NameValuePairs &pairs2)
|
||||
: m_pairs1(pairs1), m_pairs2(pairs2) {}
|
||||
|
||||
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
|
||||
{
|
||||
if (strcmp(name, "ValueNames") == 0)
|
||||
return m_pairs1.GetVoidValue(name, valueType, pValue) && m_pairs2.GetVoidValue(name, valueType, pValue);
|
||||
else
|
||||
return m_pairs1.GetVoidValue(name, valueType, pValue) || m_pairs2.GetVoidValue(name, valueType, pValue);
|
||||
}
|
||||
|
||||
const NameValuePairs &m_pairs1, &m_pairs2;
|
||||
};
|
||||
|
||||
template <class T, class BASE>
|
||||
class GetValueHelperClass
|
||||
{
|
||||
public:
|
||||
GetValueHelperClass(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst)
|
||||
: m_pObject(pObject), m_name(name), m_valueType(&valueType), m_pValue(pValue), m_found(false), m_getValueNames(false)
|
||||
{
|
||||
if (strcmp(m_name, "ValueNames") == 0)
|
||||
{
|
||||
m_found = m_getValueNames = true;
|
||||
NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(std::string), *m_valueType);
|
||||
if (searchFirst)
|
||||
searchFirst->GetVoidValue(m_name, valueType, pValue);
|
||||
if (typeid(T) != typeid(BASE))
|
||||
pObject->BASE::GetVoidValue(m_name, valueType, pValue);
|
||||
((*reinterpret_cast<std::string *>(m_pValue) += "ThisPointer:") += typeid(T).name()) += ';';
|
||||
}
|
||||
|
||||
if (!m_found && strncmp(m_name, "ThisPointer:", 12) == 0 && strcmp(m_name+12, typeid(T).name()) == 0)
|
||||
{
|
||||
NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(T *), *m_valueType);
|
||||
*reinterpret_cast<const T **>(pValue) = pObject;
|
||||
m_found = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_found && searchFirst)
|
||||
m_found = searchFirst->GetVoidValue(m_name, valueType, pValue);
|
||||
|
||||
if (!m_found && typeid(T) != typeid(BASE))
|
||||
m_found = pObject->BASE::GetVoidValue(m_name, valueType, pValue);
|
||||
}
|
||||
|
||||
operator bool() const {return m_found;}
|
||||
|
||||
template <class R>
|
||||
GetValueHelperClass<T,BASE> & operator()(const char *name, const R & (T::*pm)() const)
|
||||
{
|
||||
if (m_getValueNames)
|
||||
(*reinterpret_cast<std::string *>(m_pValue) += name) += ";";
|
||||
if (!m_found && strcmp(name, m_name) == 0)
|
||||
{
|
||||
NameValuePairs::ThrowIfTypeMismatch(name, typeid(R), *m_valueType);
|
||||
*reinterpret_cast<R *>(m_pValue) = (m_pObject->*pm)();
|
||||
m_found = true;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
GetValueHelperClass<T,BASE> &Assignable()
|
||||
{
|
||||
if (m_getValueNames)
|
||||
((*reinterpret_cast<std::string *>(m_pValue) += "ThisObject:") += typeid(T).name()) += ';';
|
||||
if (!m_found && strncmp(m_name, "ThisObject:", 11) == 0 && strcmp(m_name+11, typeid(T).name()) == 0)
|
||||
{
|
||||
NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(T), *m_valueType);
|
||||
*reinterpret_cast<T *>(m_pValue) = *m_pObject;
|
||||
m_found = true;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
const T *m_pObject;
|
||||
const char *m_name;
|
||||
const std::type_info *m_valueType;
|
||||
void *m_pValue;
|
||||
bool m_found, m_getValueNames;
|
||||
};
|
||||
|
||||
template <class BASE, class T>
|
||||
GetValueHelperClass<T, BASE> GetValueHelper(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst=NULL, BASE *dummy=NULL)
|
||||
{
|
||||
return GetValueHelperClass<T, BASE>(pObject, name, valueType, pValue, searchFirst);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
GetValueHelperClass<T, T> GetValueHelper(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst=NULL)
|
||||
{
|
||||
return GetValueHelperClass<T, T>(pObject, name, valueType, pValue, searchFirst);
|
||||
}
|
||||
|
||||
// ********************************************************
|
||||
|
||||
template <class R>
|
||||
R Hack_DefaultValueFromConstReferenceType(const R &)
|
||||
{
|
||||
return R();
|
||||
}
|
||||
|
||||
template <class R>
|
||||
bool Hack_GetValueIntoConstReference(const NameValuePairs &source, const char *name, const R &value)
|
||||
{
|
||||
return source.GetValue(name, const_cast<R &>(value));
|
||||
}
|
||||
|
||||
template <class T, class BASE>
|
||||
class AssignFromHelperClass
|
||||
{
|
||||
public:
|
||||
AssignFromHelperClass(T *pObject, const NameValuePairs &source)
|
||||
: m_pObject(pObject), m_source(source), m_done(false)
|
||||
{
|
||||
if (source.GetThisObject(*pObject))
|
||||
m_done = true;
|
||||
else if (typeid(BASE) != typeid(T))
|
||||
pObject->BASE::AssignFrom(source);
|
||||
}
|
||||
|
||||
template <class R>
|
||||
AssignFromHelperClass & operator()(const char *name, void (T::*pm)(R)) // VC60 workaround: "const R &" here causes compiler error
|
||||
{
|
||||
if (!m_done)
|
||||
{
|
||||
R value = Hack_DefaultValueFromConstReferenceType(reinterpret_cast<R>(*(int *)NULL));
|
||||
if (!Hack_GetValueIntoConstReference(m_source, name, value))
|
||||
throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name + "'");
|
||||
(m_pObject->*pm)(value);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class R, class S>
|
||||
AssignFromHelperClass & operator()(const char *name1, const char *name2, void (T::*pm)(R, S)) // VC60 workaround: "const R &" here causes compiler error
|
||||
{
|
||||
if (!m_done)
|
||||
{
|
||||
R value1 = Hack_DefaultValueFromConstReferenceType(reinterpret_cast<R>(*(int *)NULL));
|
||||
if (!Hack_GetValueIntoConstReference(m_source, name1, value1))
|
||||
throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name1 + "'");
|
||||
S value2 = Hack_DefaultValueFromConstReferenceType(reinterpret_cast<S>(*(int *)NULL));
|
||||
if (!Hack_GetValueIntoConstReference(m_source, name2, value2))
|
||||
throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name2 + "'");
|
||||
(m_pObject->*pm)(value1, value2);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
T *m_pObject;
|
||||
const NameValuePairs &m_source;
|
||||
bool m_done;
|
||||
};
|
||||
|
||||
template <class BASE, class T>
|
||||
AssignFromHelperClass<T, BASE> AssignFromHelper(T *pObject, const NameValuePairs &source, BASE *dummy=NULL)
|
||||
{
|
||||
return AssignFromHelperClass<T, BASE>(pObject, source);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
AssignFromHelperClass<T, T> AssignFromHelper(T *pObject, const NameValuePairs &source)
|
||||
{
|
||||
return AssignFromHelperClass<T, T>(pObject, source);
|
||||
}
|
||||
|
||||
// ********************************************************
|
||||
|
||||
// This should allow the linker to discard Integer code if not needed.
|
||||
extern bool (*AssignIntToInteger)(const std::type_info &valueType, void *pInteger, const void *pInt);
|
||||
|
||||
const std::type_info & IntegerTypeId();
|
||||
|
||||
template <class BASE, class T>
|
||||
class AlgorithmParameters : public NameValuePairs
|
||||
{
|
||||
public:
|
||||
AlgorithmParameters(const BASE &base, const char *name, const T &value)
|
||||
: m_base(base), m_name(name), m_value(value)
|
||||
#ifndef NDEBUG
|
||||
, m_used(false)
|
||||
#endif
|
||||
{}
|
||||
|
||||
#ifndef NDEBUG
|
||||
AlgorithmParameters(const AlgorithmParameters ©)
|
||||
: m_base(copy.m_base), m_name(copy.m_name), m_value(copy.m_value), m_used(false)
|
||||
{
|
||||
copy.m_used = true;
|
||||
}
|
||||
|
||||
// TODO: revisit after implementing some tracing mechanism, this won't work because of exceptions
|
||||
// ~AlgorithmParameters() {assert(m_used);} // use assert here because we don't want to throw out of a destructor
|
||||
#endif
|
||||
|
||||
template <class R>
|
||||
AlgorithmParameters<AlgorithmParameters<BASE,T>, R> operator()(const char *name, const R &value) const
|
||||
{
|
||||
return AlgorithmParameters<AlgorithmParameters<BASE,T>, R>(*this, name, value);
|
||||
}
|
||||
|
||||
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
|
||||
{
|
||||
if (strcmp(name, "ValueNames") == 0)
|
||||
{
|
||||
ThrowIfTypeMismatch(name, typeid(std::string), valueType);
|
||||
m_base.GetVoidValue(name, valueType, pValue);
|
||||
(*reinterpret_cast<std::string *>(pValue) += m_name) += ";";
|
||||
return true;
|
||||
}
|
||||
else if (strcmp(name, m_name) == 0)
|
||||
{
|
||||
// special case for retrieving an Integer parameter when an int was passed in
|
||||
if (!(AssignIntToInteger != NULL && typeid(T) == typeid(int) && AssignIntToInteger(valueType, pValue, &m_value)))
|
||||
{
|
||||
ThrowIfTypeMismatch(name, typeid(T), valueType);
|
||||
*reinterpret_cast<T *>(pValue) = m_value;
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
m_used = true;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return m_base.GetVoidValue(name, valueType, pValue);
|
||||
}
|
||||
|
||||
private:
|
||||
BASE m_base;
|
||||
const char *m_name;
|
||||
T m_value;
|
||||
#ifndef NDEBUG
|
||||
mutable bool m_used;
|
||||
#endif
|
||||
};
|
||||
|
||||
template <class T>
|
||||
AlgorithmParameters<NullNameValuePairs,T> MakeParameters(const char *name, const T &value)
|
||||
{
|
||||
return AlgorithmParameters<NullNameValuePairs,T>(g_nullNameValuePairs, name, value);
|
||||
}
|
||||
|
||||
#define CRYPTOPP_GET_FUNCTION_ENTRY(name) (Name::name(), &ThisClass::Get##name)
|
||||
#define CRYPTOPP_SET_FUNCTION_ENTRY(name) (Name::name(), &ThisClass::Set##name)
|
||||
#define CRYPTOPP_SET_FUNCTION_ENTRY2(name1, name2) (Name::name1(), Name::name2(), &ThisClass::Set##name1##And##name2)
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,54 @@
|
||||
#ifndef CRYPTOPP_ARGNAMES_H
|
||||
#define CRYPTOPP_ARGNAMES_H
|
||||
|
||||
#include "cryptlib.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
DOCUMENTED_NAMESPACE_BEGIN(Name)
|
||||
|
||||
#define CRYPTOPP_DEFINE_NAME_STRING(name) inline const char *name() {return #name;}
|
||||
|
||||
CRYPTOPP_DEFINE_NAME_STRING(ValueNames) //!< string, a list of value names with a semicolon (';') after each name
|
||||
CRYPTOPP_DEFINE_NAME_STRING(Version) //!< int
|
||||
CRYPTOPP_DEFINE_NAME_STRING(Seed) //!< ConstByteArrayParameter
|
||||
CRYPTOPP_DEFINE_NAME_STRING(Key) //!< ConstByteArrayParameter
|
||||
CRYPTOPP_DEFINE_NAME_STRING(IV) //!< const byte *
|
||||
CRYPTOPP_DEFINE_NAME_STRING(StolenIV) //!< byte *
|
||||
CRYPTOPP_DEFINE_NAME_STRING(Rounds) //!< int
|
||||
CRYPTOPP_DEFINE_NAME_STRING(FeedbackSize) //!< int
|
||||
CRYPTOPP_DEFINE_NAME_STRING(WordSize) //!< int, in bytes
|
||||
CRYPTOPP_DEFINE_NAME_STRING(BlockSize) //!< int, in bytes
|
||||
CRYPTOPP_DEFINE_NAME_STRING(EffectiveKeyLength) //!< int, in bits
|
||||
CRYPTOPP_DEFINE_NAME_STRING(KeySize) //!< int, in bits
|
||||
CRYPTOPP_DEFINE_NAME_STRING(ModulusSize) //!< int, in bits
|
||||
CRYPTOPP_DEFINE_NAME_STRING(SubgroupOrderSize) //!< int, in bits
|
||||
CRYPTOPP_DEFINE_NAME_STRING(PrivateExponentSize)//!< int, in bits
|
||||
CRYPTOPP_DEFINE_NAME_STRING(Modulus) //!< Integer
|
||||
CRYPTOPP_DEFINE_NAME_STRING(PublicExponent) //!< Integer
|
||||
CRYPTOPP_DEFINE_NAME_STRING(PrivateExponent) //!< Integer
|
||||
CRYPTOPP_DEFINE_NAME_STRING(PublicElement) //!< Integer
|
||||
CRYPTOPP_DEFINE_NAME_STRING(SubgroupOrder) //!< Integer
|
||||
CRYPTOPP_DEFINE_NAME_STRING(Cofactor) //!< Integer
|
||||
CRYPTOPP_DEFINE_NAME_STRING(SubgroupGenerator) //!< Integer, ECP::Point, or EC2N::Point
|
||||
CRYPTOPP_DEFINE_NAME_STRING(Curve) //!< ECP or EC2N
|
||||
CRYPTOPP_DEFINE_NAME_STRING(GroupOID) //!< OID
|
||||
CRYPTOPP_DEFINE_NAME_STRING(Prime1) //!< Integer
|
||||
CRYPTOPP_DEFINE_NAME_STRING(Prime2) //!< Integer
|
||||
CRYPTOPP_DEFINE_NAME_STRING(ModPrime1PrivateExponent) //!< Integer
|
||||
CRYPTOPP_DEFINE_NAME_STRING(ModPrime2PrivateExponent) //!< Integer
|
||||
CRYPTOPP_DEFINE_NAME_STRING(MultiplicativeInverseOfPrime2ModPrime1) //!< Integer
|
||||
CRYPTOPP_DEFINE_NAME_STRING(QuadraticResidueModPrime1) //!< Integer
|
||||
CRYPTOPP_DEFINE_NAME_STRING(QuadraticResidueModPrime2) //!< Integer
|
||||
CRYPTOPP_DEFINE_NAME_STRING(PutMessage) //!< bool
|
||||
CRYPTOPP_DEFINE_NAME_STRING(HashVerificationFilterFlags) //!< word32
|
||||
CRYPTOPP_DEFINE_NAME_STRING(SignatureVerificationFilterFlags) //!< word32
|
||||
CRYPTOPP_DEFINE_NAME_STRING(InputBuffer) //!< ConstByteArrayParameter
|
||||
CRYPTOPP_DEFINE_NAME_STRING(OutputBuffer) //!< ByteArrayParameter
|
||||
CRYPTOPP_DEFINE_NAME_STRING(XMACC_Counter) //!< word32
|
||||
|
||||
DOCUMENTED_NAMESPACE_END
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,556 @@
|
||||
// asn.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
#include "asn.h"
|
||||
|
||||
#include <iomanip>
|
||||
#include <time.h>
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
USING_NAMESPACE(std)
|
||||
|
||||
/// DER Length
|
||||
unsigned int DERLengthEncode(BufferedTransformation &bt, unsigned int length)
|
||||
{
|
||||
unsigned int i=0;
|
||||
if (length <= 0x7f)
|
||||
{
|
||||
bt.Put(byte(length));
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
bt.Put(byte(BytePrecision(length) | 0x80));
|
||||
i++;
|
||||
for (int j=BytePrecision(length); j; --j)
|
||||
{
|
||||
bt.Put(byte(length >> (j-1)*8));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
bool BERLengthDecode(BufferedTransformation &bt, unsigned int &length, bool &definiteLength)
|
||||
{
|
||||
byte b;
|
||||
|
||||
if (!bt.Get(b))
|
||||
return false;
|
||||
|
||||
if (!(b & 0x80))
|
||||
{
|
||||
definiteLength = true;
|
||||
length = b;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int lengthBytes = b & 0x7f;
|
||||
|
||||
if (lengthBytes == 0)
|
||||
{
|
||||
definiteLength = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
definiteLength = true;
|
||||
length = 0;
|
||||
while (lengthBytes--)
|
||||
{
|
||||
if (length >> (8*(sizeof(length)-1)))
|
||||
BERDecodeError(); // length about to overflow
|
||||
|
||||
if (!bt.Get(b))
|
||||
return false;
|
||||
|
||||
length = (length << 8) | b;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BERLengthDecode(BufferedTransformation &bt, unsigned int &length)
|
||||
{
|
||||
bool definiteLength;
|
||||
if (!BERLengthDecode(bt, length, definiteLength))
|
||||
BERDecodeError();
|
||||
return definiteLength;
|
||||
}
|
||||
|
||||
void DEREncodeNull(BufferedTransformation &out)
|
||||
{
|
||||
out.Put(TAG_NULL);
|
||||
out.Put(0);
|
||||
}
|
||||
|
||||
void BERDecodeNull(BufferedTransformation &in)
|
||||
{
|
||||
byte b;
|
||||
if (!in.Get(b) || b != TAG_NULL)
|
||||
BERDecodeError();
|
||||
unsigned int length;
|
||||
if (!BERLengthDecode(in, length) || length != 0)
|
||||
BERDecodeError();
|
||||
}
|
||||
|
||||
/// ASN Strings
|
||||
unsigned int DEREncodeOctetString(BufferedTransformation &bt, const byte *str, unsigned int strLen)
|
||||
{
|
||||
bt.Put(OCTET_STRING);
|
||||
unsigned int lengthBytes = DERLengthEncode(bt, strLen);
|
||||
bt.Put(str, strLen);
|
||||
return 1+lengthBytes+strLen;
|
||||
}
|
||||
|
||||
unsigned int DEREncodeOctetString(BufferedTransformation &bt, const SecByteBlock &str)
|
||||
{
|
||||
return DEREncodeOctetString(bt, str.begin(), str.size());
|
||||
}
|
||||
|
||||
unsigned int BERDecodeOctetString(BufferedTransformation &bt, SecByteBlock &str)
|
||||
{
|
||||
byte b;
|
||||
if (!bt.Get(b) || b != OCTET_STRING)
|
||||
BERDecodeError();
|
||||
|
||||
unsigned int bc;
|
||||
if (!BERLengthDecode(bt, bc))
|
||||
BERDecodeError();
|
||||
|
||||
str.resize(bc);
|
||||
if (bc != bt.Get(str, bc))
|
||||
BERDecodeError();
|
||||
return bc;
|
||||
}
|
||||
|
||||
unsigned int BERDecodeOctetString(BufferedTransformation &bt, BufferedTransformation &str)
|
||||
{
|
||||
byte b;
|
||||
if (!bt.Get(b) || b != OCTET_STRING)
|
||||
BERDecodeError();
|
||||
|
||||
unsigned int bc;
|
||||
if (!BERLengthDecode(bt, bc))
|
||||
BERDecodeError();
|
||||
|
||||
bt.TransferTo(str, bc);
|
||||
return bc;
|
||||
}
|
||||
|
||||
unsigned int DEREncodeTextString(BufferedTransformation &bt, const std::string &str, byte asnTag)
|
||||
{
|
||||
bt.Put(asnTag);
|
||||
unsigned int lengthBytes = DERLengthEncode(bt, str.size());
|
||||
bt.Put((const byte *)str.data(), str.size());
|
||||
return 1+lengthBytes+str.size();
|
||||
}
|
||||
|
||||
unsigned int BERDecodeTextString(BufferedTransformation &bt, std::string &str, byte asnTag)
|
||||
{
|
||||
byte b;
|
||||
if (!bt.Get(b) || b != asnTag)
|
||||
BERDecodeError();
|
||||
|
||||
unsigned int bc;
|
||||
if (!BERLengthDecode(bt, bc))
|
||||
BERDecodeError();
|
||||
|
||||
SecByteBlock temp(bc);
|
||||
if (bc != bt.Get(temp, bc))
|
||||
BERDecodeError();
|
||||
str.assign((char *)temp.begin(), bc);
|
||||
return bc;
|
||||
}
|
||||
|
||||
/// ASN BitString
|
||||
unsigned int DEREncodeBitString(BufferedTransformation &bt, const byte *str, unsigned int strLen, unsigned int unusedBits)
|
||||
{
|
||||
bt.Put(BIT_STRING);
|
||||
unsigned int lengthBytes = DERLengthEncode(bt, strLen+1);
|
||||
bt.Put((byte)unusedBits);
|
||||
bt.Put(str, strLen);
|
||||
return 2+lengthBytes+strLen;
|
||||
}
|
||||
|
||||
unsigned int BERDecodeBitString(BufferedTransformation &bt, SecByteBlock &str, unsigned int &unusedBits)
|
||||
{
|
||||
byte b;
|
||||
if (!bt.Get(b) || b != BIT_STRING)
|
||||
BERDecodeError();
|
||||
|
||||
unsigned int bc;
|
||||
if (!BERLengthDecode(bt, bc))
|
||||
BERDecodeError();
|
||||
|
||||
byte unused;
|
||||
if (!bt.Get(unused))
|
||||
BERDecodeError();
|
||||
unusedBits = unused;
|
||||
str.resize(bc-1);
|
||||
if ((bc-1) != bt.Get(str, bc-1))
|
||||
BERDecodeError();
|
||||
return bc-1;
|
||||
}
|
||||
|
||||
void OID::EncodeValue(BufferedTransformation &bt, unsigned long v)
|
||||
{
|
||||
for (unsigned int i=RoundUpToMultipleOf(STDMAX(7U,BitPrecision(v)), 7U)-7; i != 0; i-=7)
|
||||
bt.Put((byte)(0x80 | ((v >> i) & 0x7f)));
|
||||
bt.Put((byte)(v & 0x7f));
|
||||
}
|
||||
|
||||
unsigned int OID::DecodeValue(BufferedTransformation &bt, unsigned long &v)
|
||||
{
|
||||
byte b;
|
||||
unsigned int i=0;
|
||||
v = 0;
|
||||
while (true)
|
||||
{
|
||||
if (!bt.Get(b))
|
||||
BERDecodeError();
|
||||
i++;
|
||||
v <<= 7;
|
||||
v += b & 0x7f;
|
||||
if (!(b & 0x80))
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
void OID::DEREncode(BufferedTransformation &bt) const
|
||||
{
|
||||
assert(m_values.size() >= 2);
|
||||
ByteQueue temp;
|
||||
temp.Put(byte(m_values[0] * 40 + m_values[1]));
|
||||
for (unsigned int i=2; i<m_values.size(); i++)
|
||||
EncodeValue(temp, m_values[i]);
|
||||
bt.Put(OBJECT_IDENTIFIER);
|
||||
DERLengthEncode(bt, temp.CurrentSize());
|
||||
temp.TransferTo(bt);
|
||||
}
|
||||
|
||||
void OID::BERDecode(BufferedTransformation &bt)
|
||||
{
|
||||
byte b;
|
||||
if (!bt.Get(b) || b != OBJECT_IDENTIFIER)
|
||||
BERDecodeError();
|
||||
|
||||
unsigned int length;
|
||||
if (!BERLengthDecode(bt, length) || length < 1)
|
||||
BERDecodeError();
|
||||
|
||||
if (!bt.Get(b))
|
||||
BERDecodeError();
|
||||
|
||||
length--;
|
||||
m_values.resize(2);
|
||||
m_values[0] = b / 40;
|
||||
m_values[1] = b % 40;
|
||||
|
||||
while (length > 0)
|
||||
{
|
||||
unsigned long v;
|
||||
unsigned int valueLen = DecodeValue(bt, v);
|
||||
if (valueLen > length)
|
||||
BERDecodeError();
|
||||
m_values.push_back(v);
|
||||
length -= valueLen;
|
||||
}
|
||||
}
|
||||
|
||||
void OID::BERDecodeAndCheck(BufferedTransformation &bt) const
|
||||
{
|
||||
OID oid(bt);
|
||||
if (*this != oid)
|
||||
BERDecodeError();
|
||||
}
|
||||
|
||||
inline BufferedTransformation & EncodedObjectFilter::CurrentTarget()
|
||||
{
|
||||
if (m_flags & PUT_OBJECTS)
|
||||
return *AttachedTransformation();
|
||||
else
|
||||
return TheBitBucket();
|
||||
}
|
||||
|
||||
void EncodedObjectFilter::Put(const byte *inString, unsigned int length)
|
||||
{
|
||||
if (m_nCurrentObject == m_nObjects)
|
||||
{
|
||||
AttachedTransformation()->Put(inString, length);
|
||||
return;
|
||||
}
|
||||
|
||||
LazyPutter lazyPutter(m_queue, inString, length);
|
||||
|
||||
while (m_queue.AnyRetrievable())
|
||||
{
|
||||
switch (m_state)
|
||||
{
|
||||
case IDENTIFIER:
|
||||
if (!m_queue.Get(m_id))
|
||||
return;
|
||||
m_queue.TransferTo(CurrentTarget(), 1);
|
||||
m_state = LENGTH; // fall through
|
||||
case LENGTH:
|
||||
{
|
||||
byte b;
|
||||
if (m_level > 0 && m_id == 0 && m_queue.Peek(b) && b == 0)
|
||||
{
|
||||
m_queue.TransferTo(CurrentTarget(), 1);
|
||||
m_level--;
|
||||
m_state = IDENTIFIER;
|
||||
break;
|
||||
}
|
||||
ByteQueue::Walker walker(m_queue);
|
||||
bool definiteLength;
|
||||
if (!BERLengthDecode(walker, m_lengthRemaining, definiteLength))
|
||||
return;
|
||||
m_queue.TransferTo(CurrentTarget(), walker.GetCurrentPosition());
|
||||
if (!((m_id & CONSTRUCTED) || definiteLength))
|
||||
BERDecodeError();
|
||||
if (!definiteLength)
|
||||
{
|
||||
if (!(m_id & CONSTRUCTED))
|
||||
BERDecodeError();
|
||||
m_level++;
|
||||
m_state = IDENTIFIER;
|
||||
break;
|
||||
}
|
||||
m_state = BODY; // fall through
|
||||
}
|
||||
case BODY:
|
||||
m_lengthRemaining -= m_queue.TransferTo(CurrentTarget(), m_lengthRemaining);
|
||||
|
||||
if (m_lengthRemaining == 0)
|
||||
m_state = IDENTIFIER;
|
||||
}
|
||||
|
||||
if (m_state == IDENTIFIER && m_level == 0)
|
||||
{
|
||||
// just finished processing a level 0 object
|
||||
++m_nCurrentObject;
|
||||
|
||||
if (m_flags & PUT_MESSANGE_END_AFTER_EACH_OBJECT)
|
||||
AttachedTransformation()->MessageEnd();
|
||||
|
||||
if (m_nCurrentObject == m_nObjects)
|
||||
{
|
||||
if (m_flags & PUT_MESSANGE_END_AFTER_ALL_OBJECTS)
|
||||
AttachedTransformation()->MessageEnd();
|
||||
|
||||
if (m_flags & PUT_MESSANGE_SERIES_END_AFTER_ALL_OBJECTS)
|
||||
AttachedTransformation()->MessageSeriesEnd();
|
||||
|
||||
m_queue.TransferAllTo(*AttachedTransformation());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BERGeneralDecoder::BERGeneralDecoder(BufferedTransformation &inQueue, byte asnTag)
|
||||
: m_inQueue(inQueue), m_finished(false)
|
||||
{
|
||||
byte b;
|
||||
if (!m_inQueue.Get(b) || b != asnTag)
|
||||
BERDecodeError();
|
||||
|
||||
m_definiteLength = BERLengthDecode(m_inQueue, m_length);
|
||||
}
|
||||
|
||||
BERGeneralDecoder::BERGeneralDecoder(BERGeneralDecoder &inQueue, byte asnTag)
|
||||
: m_inQueue(inQueue), m_finished(false)
|
||||
{
|
||||
byte b;
|
||||
if (!m_inQueue.Get(b) || b != asnTag)
|
||||
BERDecodeError();
|
||||
|
||||
m_definiteLength = BERLengthDecode(m_inQueue, m_length);
|
||||
if (!m_definiteLength && !(asnTag & CONSTRUCTED))
|
||||
BERDecodeError(); // cannot be primitive have indefinite length
|
||||
}
|
||||
|
||||
BERGeneralDecoder::~BERGeneralDecoder()
|
||||
{
|
||||
try // avoid throwing in constructor
|
||||
{
|
||||
if (!m_finished)
|
||||
MessageEnd();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
bool BERGeneralDecoder::EndReached() const
|
||||
{
|
||||
if (m_definiteLength)
|
||||
return m_length == 0;
|
||||
else
|
||||
{ // check end-of-content octets
|
||||
word16 i;
|
||||
return (m_inQueue.PeekWord16(i)==2 && i==0);
|
||||
}
|
||||
}
|
||||
|
||||
byte BERGeneralDecoder::PeekByte() const
|
||||
{
|
||||
byte b;
|
||||
if (!Peek(b))
|
||||
BERDecodeError();
|
||||
return b;
|
||||
}
|
||||
|
||||
void BERGeneralDecoder::CheckByte(byte check)
|
||||
{
|
||||
byte b;
|
||||
if (!Get(b) || b != check)
|
||||
BERDecodeError();
|
||||
}
|
||||
|
||||
void BERGeneralDecoder::MessageEnd()
|
||||
{
|
||||
m_finished = true;
|
||||
if (m_definiteLength)
|
||||
{
|
||||
if (m_length != 0)
|
||||
BERDecodeError();
|
||||
}
|
||||
else
|
||||
{ // remove end-of-content octets
|
||||
word16 i;
|
||||
if (m_inQueue.GetWord16(i) != 2 || i != 0)
|
||||
BERDecodeError();
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int BERGeneralDecoder::TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel, bool blocking)
|
||||
{
|
||||
if (m_definiteLength && transferBytes > m_length)
|
||||
transferBytes = m_length;
|
||||
unsigned int blockedBytes = m_inQueue.TransferTo2(target, transferBytes, channel, blocking);
|
||||
ReduceLength(transferBytes);
|
||||
return blockedBytes;
|
||||
}
|
||||
|
||||
unsigned int BERGeneralDecoder::CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end, const std::string &channel, bool blocking) const
|
||||
{
|
||||
if (m_definiteLength)
|
||||
end = STDMIN((unsigned long)m_length, end);
|
||||
return m_inQueue.CopyRangeTo2(target, begin, end, channel, blocking);
|
||||
}
|
||||
|
||||
unsigned int BERGeneralDecoder::ReduceLength(unsigned int delta)
|
||||
{
|
||||
if (m_definiteLength)
|
||||
{
|
||||
if (m_length < delta)
|
||||
BERDecodeError();
|
||||
m_length -= delta;
|
||||
}
|
||||
return delta;
|
||||
}
|
||||
|
||||
DERGeneralEncoder::DERGeneralEncoder(BufferedTransformation &outQueue, byte asnTag)
|
||||
: m_outQueue(outQueue), m_finished(false), m_asnTag(asnTag)
|
||||
{
|
||||
}
|
||||
|
||||
DERGeneralEncoder::DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag)
|
||||
: m_outQueue(outQueue), m_finished(false), m_asnTag(asnTag)
|
||||
{
|
||||
}
|
||||
|
||||
DERGeneralEncoder::~DERGeneralEncoder()
|
||||
{
|
||||
try // avoid throwing in constructor
|
||||
{
|
||||
if (!m_finished)
|
||||
MessageEnd();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void DERGeneralEncoder::MessageEnd()
|
||||
{
|
||||
m_finished = true;
|
||||
unsigned int length = (unsigned int)CurrentSize();
|
||||
m_outQueue.Put(m_asnTag);
|
||||
DERLengthEncode(m_outQueue, length);
|
||||
TransferTo(m_outQueue);
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
|
||||
void X509PublicKey::BERDecode(BufferedTransformation &bt)
|
||||
{
|
||||
BERSequenceDecoder subjectPublicKeyInfo(bt);
|
||||
BERSequenceDecoder algorithm(subjectPublicKeyInfo);
|
||||
GetAlgorithmID().BERDecodeAndCheck(algorithm);
|
||||
bool parametersPresent = algorithm.EndReached() ? false : BERDecodeAlgorithmParameters(algorithm);
|
||||
algorithm.MessageEnd();
|
||||
|
||||
BERGeneralDecoder subjectPublicKey(subjectPublicKeyInfo, BIT_STRING);
|
||||
subjectPublicKey.CheckByte(0); // unused bits
|
||||
BERDecodeKey2(subjectPublicKey, parametersPresent, subjectPublicKey.RemainingLength());
|
||||
subjectPublicKey.MessageEnd();
|
||||
subjectPublicKeyInfo.MessageEnd();
|
||||
}
|
||||
|
||||
void X509PublicKey::DEREncode(BufferedTransformation &bt) const
|
||||
{
|
||||
DERSequenceEncoder subjectPublicKeyInfo(bt);
|
||||
|
||||
DERSequenceEncoder algorithm(subjectPublicKeyInfo);
|
||||
GetAlgorithmID().DEREncode(algorithm);
|
||||
DEREncodeAlgorithmParameters(algorithm);
|
||||
algorithm.MessageEnd();
|
||||
|
||||
DERGeneralEncoder subjectPublicKey(subjectPublicKeyInfo, BIT_STRING);
|
||||
subjectPublicKey.Put(0); // unused bits
|
||||
DEREncodeKey(subjectPublicKey);
|
||||
subjectPublicKey.MessageEnd();
|
||||
|
||||
subjectPublicKeyInfo.MessageEnd();
|
||||
}
|
||||
|
||||
void PKCS8PrivateKey::BERDecode(BufferedTransformation &bt)
|
||||
{
|
||||
BERSequenceDecoder privateKeyInfo(bt);
|
||||
word32 version;
|
||||
BERDecodeUnsigned<word32>(privateKeyInfo, version, INTEGER, 0, 0); // check version
|
||||
|
||||
BERSequenceDecoder algorithm(privateKeyInfo);
|
||||
GetAlgorithmID().BERDecodeAndCheck(algorithm);
|
||||
bool parametersPresent = BERDecodeAlgorithmParameters(algorithm);
|
||||
algorithm.MessageEnd();
|
||||
|
||||
BERGeneralDecoder octetString(privateKeyInfo, OCTET_STRING);
|
||||
BERDecodeKey2(octetString, parametersPresent, privateKeyInfo.RemainingLength());
|
||||
octetString.MessageEnd();
|
||||
|
||||
BERDecodeOptionalAttributes(privateKeyInfo);
|
||||
privateKeyInfo.MessageEnd();
|
||||
}
|
||||
|
||||
void PKCS8PrivateKey::DEREncode(BufferedTransformation &bt) const
|
||||
{
|
||||
DERSequenceEncoder privateKeyInfo(bt);
|
||||
DEREncodeUnsigned<word32>(privateKeyInfo, 0); // version
|
||||
|
||||
DERSequenceEncoder algorithm(privateKeyInfo);
|
||||
GetAlgorithmID().DEREncode(algorithm);
|
||||
DEREncodeAlgorithmParameters(algorithm);
|
||||
algorithm.MessageEnd();
|
||||
|
||||
DERGeneralEncoder octetString(privateKeyInfo, OCTET_STRING);
|
||||
DEREncodeKey(octetString);
|
||||
octetString.MessageEnd();
|
||||
|
||||
DEREncodeOptionalAttributes(privateKeyInfo);
|
||||
privateKeyInfo.MessageEnd();
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -0,0 +1,346 @@
|
||||
#ifndef CRYPTOPP_ASN_H
|
||||
#define CRYPTOPP_ASN_H
|
||||
|
||||
#include "filters.h"
|
||||
#include "queue.h"
|
||||
#include <vector>
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
// these tags and flags are not complete
|
||||
enum ASNTag
|
||||
{
|
||||
BOOLEAN = 0x01,
|
||||
INTEGER = 0x02,
|
||||
BIT_STRING = 0x03,
|
||||
OCTET_STRING = 0x04,
|
||||
TAG_NULL = 0x05,
|
||||
OBJECT_IDENTIFIER = 0x06,
|
||||
OBJECT_DESCRIPTOR = 0x07,
|
||||
EXTERNAL = 0x08,
|
||||
REAL = 0x09,
|
||||
ENUMERATED = 0x0a,
|
||||
UTF8_STRING = 0x0c,
|
||||
SEQUENCE = 0x10,
|
||||
SET = 0x11,
|
||||
NUMERIC_STRING = 0x12,
|
||||
PRINTABLE_STRING = 0x13,
|
||||
T61_STRING = 0x14,
|
||||
VIDEOTEXT_STRING = 0x15,
|
||||
IA5_STRING = 0x16,
|
||||
UTC_TIME = 0x17,
|
||||
GENERALIZED_TIME = 0x18,
|
||||
GRAPHIC_STRING = 0x19,
|
||||
VISIBLE_STRING = 0x1a,
|
||||
GENERAL_STRING = 0x1b
|
||||
};
|
||||
|
||||
enum ASNIdFlag
|
||||
{
|
||||
UNIVERSAL = 0x00,
|
||||
// DATA = 0x01,
|
||||
// HEADER = 0x02,
|
||||
CONSTRUCTED = 0x20,
|
||||
APPLICATION = 0x40,
|
||||
CONTEXT_SPECIFIC = 0x80,
|
||||
PRIVATE = 0xc0
|
||||
};
|
||||
|
||||
inline void BERDecodeError() {throw BERDecodeErr();}
|
||||
|
||||
class UnknownOID : public BERDecodeErr
|
||||
{
|
||||
public:
|
||||
UnknownOID() : BERDecodeErr("BER decode error: unknown object identifier") {}
|
||||
UnknownOID(const char *err) : BERDecodeErr(err) {}
|
||||
};
|
||||
|
||||
// unsigned int DERLengthEncode(unsigned int length, byte *output=0);
|
||||
unsigned int DERLengthEncode(BufferedTransformation &out, unsigned int length);
|
||||
// returns false if indefinite length
|
||||
bool BERLengthDecode(BufferedTransformation &in, unsigned int &length);
|
||||
|
||||
void DEREncodeNull(BufferedTransformation &out);
|
||||
void BERDecodeNull(BufferedTransformation &in);
|
||||
|
||||
unsigned int DEREncodeOctetString(BufferedTransformation &out, const byte *str, unsigned int strLen);
|
||||
unsigned int DEREncodeOctetString(BufferedTransformation &out, const SecByteBlock &str);
|
||||
unsigned int BERDecodeOctetString(BufferedTransformation &in, SecByteBlock &str);
|
||||
unsigned int BERDecodeOctetString(BufferedTransformation &in, BufferedTransformation &str);
|
||||
|
||||
// for UTF8_STRING, PRINTABLE_STRING, and IA5_STRING
|
||||
unsigned int DEREncodeTextString(BufferedTransformation &out, const std::string &str, byte asnTag);
|
||||
unsigned int BERDecodeTextString(BufferedTransformation &in, std::string &str, byte asnTag);
|
||||
|
||||
unsigned int DEREncodeBitString(BufferedTransformation &out, const byte *str, unsigned int strLen, unsigned int unusedBits=0);
|
||||
unsigned int BERDecodeBitString(BufferedTransformation &in, SecByteBlock &str, unsigned int &unusedBits);
|
||||
|
||||
//! Object Identifier
|
||||
class OID
|
||||
{
|
||||
public:
|
||||
OID() {}
|
||||
OID(unsigned long v) : m_values(1, v) {}
|
||||
OID(BufferedTransformation &bt) {BERDecode(bt);}
|
||||
|
||||
inline OID & operator+=(unsigned long rhs) {m_values.push_back(rhs); return *this;}
|
||||
|
||||
void DEREncode(BufferedTransformation &bt) const;
|
||||
void BERDecode(BufferedTransformation &bt);
|
||||
|
||||
// throw BERDecodeErr() if decoded value doesn't equal this OID
|
||||
void BERDecodeAndCheck(BufferedTransformation &bt) const;
|
||||
|
||||
std::vector<unsigned long> m_values;
|
||||
|
||||
private:
|
||||
static void EncodeValue(BufferedTransformation &bt, unsigned long v);
|
||||
static unsigned int DecodeValue(BufferedTransformation &bt, unsigned long &v);
|
||||
};
|
||||
|
||||
class EncodedObjectFilter : public Filter
|
||||
{
|
||||
public:
|
||||
enum Flag {PUT_OBJECTS=1, PUT_MESSANGE_END_AFTER_EACH_OBJECT=2, PUT_MESSANGE_END_AFTER_ALL_OBJECTS=4, PUT_MESSANGE_SERIES_END_AFTER_ALL_OBJECTS=8};
|
||||
EncodedObjectFilter(BufferedTransformation *attachment = NULL, unsigned int nObjects = 1, word32 flags = 0);
|
||||
|
||||
void Put(const byte *inString, unsigned int length);
|
||||
|
||||
unsigned int GetNumberOfCompletedObjects() const {return m_nCurrentObject;}
|
||||
unsigned long GetPositionOfObject(unsigned int i) const {return m_positions[i];}
|
||||
|
||||
private:
|
||||
BufferedTransformation & CurrentTarget();
|
||||
|
||||
word32 m_flags;
|
||||
unsigned int m_nObjects, m_nCurrentObject, m_level;
|
||||
std::vector<unsigned int> m_positions;
|
||||
ByteQueue m_queue;
|
||||
enum State {IDENTIFIER, LENGTH, BODY, TAIL, ALL_DONE} m_state;
|
||||
byte m_id;
|
||||
unsigned int m_lengthRemaining;
|
||||
};
|
||||
|
||||
//! BER General Decoder
|
||||
class BERGeneralDecoder : public Store
|
||||
{
|
||||
public:
|
||||
explicit BERGeneralDecoder(BufferedTransformation &inQueue, byte asnTag);
|
||||
explicit BERGeneralDecoder(BERGeneralDecoder &inQueue, byte asnTag);
|
||||
~BERGeneralDecoder();
|
||||
|
||||
bool IsDefiniteLength() const {return m_definiteLength;}
|
||||
unsigned int RemainingLength() const {assert(m_definiteLength); return m_length;}
|
||||
bool EndReached() const;
|
||||
byte PeekByte() const;
|
||||
void CheckByte(byte b);
|
||||
|
||||
unsigned int TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel=NULL_CHANNEL, bool blocking=true);
|
||||
unsigned int CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end=ULONG_MAX, const std::string &channel=NULL_CHANNEL, bool blocking=true) const;
|
||||
|
||||
// call this to denote end of sequence
|
||||
void MessageEnd();
|
||||
|
||||
protected:
|
||||
BufferedTransformation &m_inQueue;
|
||||
bool m_finished, m_definiteLength;
|
||||
unsigned int m_length;
|
||||
|
||||
private:
|
||||
void StoreInitialize(const NameValuePairs ¶meters) {assert(false);}
|
||||
unsigned int ReduceLength(unsigned int delta);
|
||||
};
|
||||
|
||||
//! DER General Encoder
|
||||
class DERGeneralEncoder : public ByteQueue
|
||||
{
|
||||
public:
|
||||
explicit DERGeneralEncoder(BufferedTransformation &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED);
|
||||
explicit DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED);
|
||||
~DERGeneralEncoder();
|
||||
|
||||
// call this to denote end of sequence
|
||||
void MessageEnd();
|
||||
|
||||
private:
|
||||
BufferedTransformation &m_outQueue;
|
||||
bool m_finished;
|
||||
|
||||
byte m_asnTag;
|
||||
};
|
||||
|
||||
//! BER Sequence Decoder
|
||||
class BERSequenceDecoder : public BERGeneralDecoder
|
||||
{
|
||||
public:
|
||||
explicit BERSequenceDecoder(BufferedTransformation &inQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
|
||||
: BERGeneralDecoder(inQueue, asnTag) {}
|
||||
explicit BERSequenceDecoder(BERSequenceDecoder &inQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
|
||||
: BERGeneralDecoder(inQueue, asnTag) {}
|
||||
};
|
||||
|
||||
//! DER Sequence Encoder
|
||||
class DERSequenceEncoder : public DERGeneralEncoder
|
||||
{
|
||||
public:
|
||||
explicit DERSequenceEncoder(BufferedTransformation &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
|
||||
: DERGeneralEncoder(outQueue, asnTag) {}
|
||||
explicit DERSequenceEncoder(DERSequenceEncoder &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
|
||||
: DERGeneralEncoder(outQueue, asnTag) {}
|
||||
};
|
||||
|
||||
//! BER Set Decoder
|
||||
class BERSetDecoder : public BERGeneralDecoder
|
||||
{
|
||||
public:
|
||||
explicit BERSetDecoder(BufferedTransformation &inQueue, byte asnTag = SET | CONSTRUCTED)
|
||||
: BERGeneralDecoder(inQueue, asnTag) {}
|
||||
explicit BERSetDecoder(BERSetDecoder &inQueue, byte asnTag = SET | CONSTRUCTED)
|
||||
: BERGeneralDecoder(inQueue, asnTag) {}
|
||||
};
|
||||
|
||||
//! DER Set Encoder
|
||||
class DERSetEncoder : public DERGeneralEncoder
|
||||
{
|
||||
public:
|
||||
explicit DERSetEncoder(BufferedTransformation &outQueue, byte asnTag = SET | CONSTRUCTED)
|
||||
: DERGeneralEncoder(outQueue, asnTag) {}
|
||||
explicit DERSetEncoder(DERSetEncoder &outQueue, byte asnTag = SET | CONSTRUCTED)
|
||||
: DERGeneralEncoder(outQueue, asnTag) {}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class ASNOptional : public member_ptr<T>
|
||||
{
|
||||
public:
|
||||
void BERDecode(BERSequenceDecoder &seqDecoder, byte tag, byte mask = ~CONSTRUCTED)
|
||||
{
|
||||
byte b;
|
||||
if (seqDecoder.Peek(b) && (b & mask) == tag)
|
||||
reset(new T(seqDecoder));
|
||||
}
|
||||
void DEREncode(BufferedTransformation &out)
|
||||
{
|
||||
if (get() != NULL)
|
||||
get()->DEREncode(out);
|
||||
}
|
||||
};
|
||||
|
||||
//! .
|
||||
class ASN1Key : public ASN1CryptoMaterial
|
||||
{
|
||||
public:
|
||||
virtual OID GetAlgorithmID() const =0;
|
||||
virtual bool BERDecodeAlgorithmParameters(BufferedTransformation &bt)
|
||||
{BERDecodeNull(bt); return false;}
|
||||
virtual bool DEREncodeAlgorithmParameters(BufferedTransformation &bt) const
|
||||
{DEREncodeNull(bt); return false;} // see RFC 2459, section 7.3.1
|
||||
// one of the following two should be overriden
|
||||
//! decode subjectPublicKey part of subjectPublicKeyInfo, or privateKey part of privateKeyInfo, without the BIT STRING or OCTET STRING header
|
||||
virtual void BERDecodeKey(BufferedTransformation &bt) {assert(false);}
|
||||
virtual void BERDecodeKey2(BufferedTransformation &bt, bool parametersPresent, unsigned int size)
|
||||
{BERDecodeKey(bt);}
|
||||
//! encode subjectPublicKey part of subjectPublicKeyInfo, or privateKey part of privateKeyInfo, without the BIT STRING or OCTET STRING header
|
||||
virtual void DEREncodeKey(BufferedTransformation &bt) const =0;
|
||||
};
|
||||
|
||||
//! encodes/decodes subjectPublicKeyInfo
|
||||
class X509PublicKey : virtual public ASN1Key, public PublicKey
|
||||
{
|
||||
public:
|
||||
void BERDecode(BufferedTransformation &bt);
|
||||
void DEREncode(BufferedTransformation &bt) const;
|
||||
};
|
||||
|
||||
//! encodes/decodes privateKeyInfo
|
||||
class PKCS8PrivateKey : virtual public ASN1Key, public PrivateKey
|
||||
{
|
||||
public:
|
||||
void BERDecode(BufferedTransformation &bt);
|
||||
void DEREncode(BufferedTransformation &bt) const;
|
||||
|
||||
virtual void BERDecodeOptionalAttributes(BufferedTransformation &bt)
|
||||
{} // TODO: skip optional attributes if present
|
||||
virtual void DEREncodeOptionalAttributes(BufferedTransformation &bt) const
|
||||
{}
|
||||
};
|
||||
|
||||
// ********************************************************
|
||||
|
||||
//! DER Encode Unsigned
|
||||
/*! for INTEGER, BOOLEAN, and ENUM */
|
||||
template <class T>
|
||||
unsigned int DEREncodeUnsigned(BufferedTransformation &out, T w, byte asnTag = INTEGER)
|
||||
{
|
||||
byte buf[sizeof(w)+1];
|
||||
unsigned int bc;
|
||||
if (asnTag == BOOLEAN)
|
||||
{
|
||||
buf[sizeof(w)] = w ? 0xff : 0;
|
||||
bc = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
buf[0] = 0;
|
||||
for (unsigned int i=0; i<sizeof(w); i++)
|
||||
buf[i+1] = byte(w >> (sizeof(w)-1-i)*8);
|
||||
bc = sizeof(w);
|
||||
while (bc > 1 && buf[sizeof(w)+1-bc] == 0)
|
||||
--bc;
|
||||
if (buf[sizeof(w)+1-bc] & 0x80)
|
||||
++bc;
|
||||
}
|
||||
out.Put(asnTag);
|
||||
unsigned int lengthBytes = DERLengthEncode(out, bc);
|
||||
out.Put(buf+sizeof(w)+1-bc, bc);
|
||||
return 1+lengthBytes+bc;
|
||||
}
|
||||
|
||||
//! BER Decode Unsigned
|
||||
// VC60 workaround: std::numeric_limits<T>::max conflicts with MFC max macro
|
||||
// CW41 workaround: std::numeric_limits<T>::max causes a template error
|
||||
template <class T>
|
||||
void BERDecodeUnsigned(BufferedTransformation &in, T &w, byte asnTag = INTEGER,
|
||||
T minValue = 0, T maxValue = 0xffffffff)
|
||||
{
|
||||
byte b;
|
||||
if (!in.Get(b) || b != asnTag)
|
||||
BERDecodeError();
|
||||
|
||||
unsigned int bc;
|
||||
BERLengthDecode(in, bc);
|
||||
|
||||
SecByteBlock buf(bc);
|
||||
|
||||
if (bc != in.Get(buf, bc))
|
||||
BERDecodeError();
|
||||
|
||||
const byte *ptr = buf;
|
||||
while (bc > sizeof(w) && *ptr == 0)
|
||||
{
|
||||
bc--;
|
||||
ptr++;
|
||||
}
|
||||
if (bc > sizeof(w))
|
||||
BERDecodeError();
|
||||
|
||||
w = 0;
|
||||
for (unsigned int i=0; i<bc; i++)
|
||||
w = (w << 8) | ptr[i];
|
||||
|
||||
if (w < minValue || w > maxValue)
|
||||
BERDecodeError();
|
||||
}
|
||||
|
||||
inline bool operator==(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs)
|
||||
{return lhs.m_values == rhs.m_values;}
|
||||
inline bool operator!=(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs)
|
||||
{return lhs.m_values != rhs.m_values;}
|
||||
inline bool operator<(const ::CryptoPP::OID &lhs, const ::CryptoPP::OID &rhs)
|
||||
{return std::lexicographical_compare(lhs.m_values.begin(), lhs.m_values.end(), rhs.m_values.begin(), rhs.m_values.end());}
|
||||
inline ::CryptoPP::OID operator+(const ::CryptoPP::OID &lhs, unsigned long rhs)
|
||||
{return ::CryptoPP::OID(lhs)+=rhs;}
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,228 @@
|
||||
// basecode.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
#include "basecode.h"
|
||||
#include "fltrimpl.h"
|
||||
#include <ctype.h>
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
void BaseN_Encoder::IsolatedInitialize(const NameValuePairs ¶meters)
|
||||
{
|
||||
parameters.GetRequiredParameter("BaseN_Encoder", "EncodingLookupArray", m_alphabet);
|
||||
|
||||
parameters.GetRequiredIntParameter("BaseN_Encoder", "Log2Base", m_bitsPerChar);
|
||||
if (m_bitsPerChar <= 0 || m_bitsPerChar >= 8)
|
||||
throw InvalidArgument("BaseN_Encoder: Log2Base must be between 1 and 7 inclusive");
|
||||
|
||||
byte padding;
|
||||
bool pad;
|
||||
if (parameters.GetValue("PaddingByte", padding))
|
||||
pad = parameters.GetValueWithDefault("Pad", true);
|
||||
else
|
||||
pad = false;
|
||||
m_padding = pad ? padding : -1;
|
||||
|
||||
m_bytePos = m_bitPos = 0;
|
||||
|
||||
int i = 8;
|
||||
while (i%m_bitsPerChar != 0)
|
||||
i += 8;
|
||||
m_outputBlockSize = i/m_bitsPerChar;
|
||||
|
||||
m_outBuf.New(m_outputBlockSize);
|
||||
}
|
||||
|
||||
unsigned int BaseN_Encoder::Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking)
|
||||
{
|
||||
FILTER_BEGIN;
|
||||
while (m_inputPosition < length)
|
||||
{
|
||||
if (m_bytePos == 0)
|
||||
memset(m_outBuf, 0, m_outputBlockSize);
|
||||
|
||||
{
|
||||
unsigned int b = begin[m_inputPosition++], bitsLeftInSource = 8;
|
||||
while (true)
|
||||
{
|
||||
assert(m_bitPos < m_bitsPerChar);
|
||||
unsigned int bitsLeftInTarget = m_bitsPerChar-m_bitPos;
|
||||
m_outBuf[m_bytePos] |= b >> (8-bitsLeftInTarget);
|
||||
if (bitsLeftInSource >= bitsLeftInTarget)
|
||||
{
|
||||
m_bitPos = 0;
|
||||
++m_bytePos;
|
||||
bitsLeftInSource -= bitsLeftInTarget;
|
||||
if (bitsLeftInSource == 0)
|
||||
break;
|
||||
b <<= bitsLeftInTarget;
|
||||
b &= 0xff;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_bitPos += bitsLeftInSource;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert(m_bytePos <= m_outputBlockSize);
|
||||
if (m_bytePos == m_outputBlockSize)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<m_bytePos; i++)
|
||||
{
|
||||
assert(m_outBuf[i] < (1 << m_bitsPerChar));
|
||||
m_outBuf[i] = m_alphabet[m_outBuf[i]];
|
||||
}
|
||||
FILTER_OUTPUT(1, m_outBuf, m_outputBlockSize, 0);
|
||||
|
||||
m_bytePos = m_bitPos = 0;
|
||||
}
|
||||
}
|
||||
if (messageEnd)
|
||||
{
|
||||
if (m_bitPos > 0)
|
||||
++m_bytePos;
|
||||
|
||||
int i;
|
||||
for (i=0; i<m_bytePos; i++)
|
||||
m_outBuf[i] = m_alphabet[m_outBuf[i]];
|
||||
|
||||
if (m_padding != -1 && m_bytePos > 0)
|
||||
{
|
||||
memset(m_outBuf+m_bytePos, m_padding, m_outputBlockSize-m_bytePos);
|
||||
m_bytePos = m_outputBlockSize;
|
||||
}
|
||||
FILTER_OUTPUT(2, m_outBuf, m_bytePos, messageEnd);
|
||||
m_bytePos = m_bitPos = 0;
|
||||
}
|
||||
FILTER_END_NO_MESSAGE_END;
|
||||
}
|
||||
|
||||
void BaseN_Decoder::IsolatedInitialize(const NameValuePairs ¶meters)
|
||||
{
|
||||
parameters.GetRequiredParameter("BaseN_Decoder", "DecodingLookupArray", m_lookup);
|
||||
|
||||
parameters.GetRequiredIntParameter("BaseN_Decoder", "Log2Base", m_bitsPerChar);
|
||||
if (m_bitsPerChar <= 0 || m_bitsPerChar >= 8)
|
||||
throw InvalidArgument("BaseN_Decoder: Log2Base must be between 1 and 7 inclusive");
|
||||
|
||||
m_bytePos = m_bitPos = 0;
|
||||
|
||||
int i = m_bitsPerChar;
|
||||
while (i%8 != 0)
|
||||
i += m_bitsPerChar;
|
||||
m_outputBlockSize = i/8;
|
||||
|
||||
m_outBuf.New(m_outputBlockSize);
|
||||
}
|
||||
|
||||
unsigned int BaseN_Decoder::Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking)
|
||||
{
|
||||
FILTER_BEGIN;
|
||||
while (m_inputPosition < length)
|
||||
{
|
||||
unsigned int value;
|
||||
value = m_lookup[begin[m_inputPosition++]];
|
||||
if (value >= 256)
|
||||
continue;
|
||||
|
||||
if (m_bytePos == 0 && m_bitPos == 0)
|
||||
memset(m_outBuf, 0, m_outputBlockSize);
|
||||
|
||||
{
|
||||
int newBitPos = m_bitPos + m_bitsPerChar;
|
||||
if (newBitPos <= 8)
|
||||
m_outBuf[m_bytePos] |= value << (8-newBitPos);
|
||||
else
|
||||
{
|
||||
m_outBuf[m_bytePos] |= value >> (newBitPos-8);
|
||||
m_outBuf[m_bytePos+1] |= value << (16-newBitPos);
|
||||
}
|
||||
|
||||
m_bitPos = newBitPos;
|
||||
while (m_bitPos >= 8)
|
||||
{
|
||||
m_bitPos -= 8;
|
||||
++m_bytePos;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_bytePos == m_outputBlockSize)
|
||||
{
|
||||
FILTER_OUTPUT(1, m_outBuf, m_outputBlockSize, 0);
|
||||
m_bytePos = m_bitPos = 0;
|
||||
}
|
||||
}
|
||||
if (messageEnd)
|
||||
{
|
||||
FILTER_OUTPUT(2, m_outBuf, m_bytePos, messageEnd);
|
||||
m_bytePos = m_bitPos = 0;
|
||||
}
|
||||
FILTER_END_NO_MESSAGE_END;
|
||||
}
|
||||
|
||||
void BaseN_Decoder::InitializeDecodingLookupArray(int *lookup, const byte *alphabet, unsigned int base, bool caseInsensitive)
|
||||
{
|
||||
std::fill(lookup, lookup+256, -1);
|
||||
|
||||
for (unsigned int i=0; i<base; i++)
|
||||
{
|
||||
if (caseInsensitive && isalpha(alphabet[i]))
|
||||
{
|
||||
assert(lookup[toupper(alphabet[i])] == -1);
|
||||
lookup[toupper(alphabet[i])] = i;
|
||||
assert(lookup[tolower(alphabet[i])] == -1);
|
||||
lookup[tolower(alphabet[i])] = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(lookup[alphabet[i]] == -1);
|
||||
lookup[alphabet[i]] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Grouper::IsolatedInitialize(const NameValuePairs ¶meters)
|
||||
{
|
||||
m_groupSize = parameters.GetIntValueWithDefault("GroupSize", 0);
|
||||
ConstByteArrayParameter separator, terminator;
|
||||
if (m_groupSize)
|
||||
parameters.GetRequiredParameter("Grouper", "Separator", separator);
|
||||
parameters.GetValue("Terminator", terminator);
|
||||
|
||||
m_separator.Assign(separator.begin(), separator.size());
|
||||
m_terminator.Assign(terminator.begin(), terminator.size());
|
||||
m_counter = 0;
|
||||
}
|
||||
|
||||
unsigned int Grouper::Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking)
|
||||
{
|
||||
FILTER_BEGIN;
|
||||
if (m_groupSize)
|
||||
{
|
||||
while (m_inputPosition < length)
|
||||
{
|
||||
if (m_counter == m_groupSize)
|
||||
{
|
||||
FILTER_OUTPUT(1, m_separator, m_separator.size(), 0);
|
||||
m_counter = 0;
|
||||
}
|
||||
|
||||
unsigned int len;
|
||||
FILTER_OUTPUT2(2, len = STDMIN(length-m_inputPosition, m_groupSize-m_counter),
|
||||
begin+m_inputPosition, len, 0);
|
||||
m_inputPosition += len;
|
||||
m_counter += len;
|
||||
}
|
||||
}
|
||||
else
|
||||
FILTER_OUTPUT(3, begin, length, 0);
|
||||
|
||||
if (messageEnd)
|
||||
FILTER_OUTPUT(4, m_terminator, m_terminator.size(), messageEnd);
|
||||
FILTER_END_NO_MESSAGE_END
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -0,0 +1,82 @@
|
||||
#ifndef CRYPTOPP_BASECODE_H
|
||||
#define CRYPTOPP_BASECODE_H
|
||||
|
||||
#include "filters.h"
|
||||
#include "algparam.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
class BaseN_Encoder : public Unflushable<Filter>
|
||||
{
|
||||
public:
|
||||
BaseN_Encoder(BufferedTransformation *attachment=NULL)
|
||||
: Unflushable<Filter>(attachment) {}
|
||||
|
||||
BaseN_Encoder(const byte *alphabet, int log2base, BufferedTransformation *attachment=NULL, int padding=-1)
|
||||
: Unflushable<Filter>(attachment)
|
||||
{
|
||||
IsolatedInitialize(MakeParameters("EncodingLookupArray", alphabet)
|
||||
("Log2Base", log2base)
|
||||
("Pad", padding != -1)
|
||||
("PaddingByte", byte(padding)));
|
||||
}
|
||||
|
||||
void IsolatedInitialize(const NameValuePairs ¶meters);
|
||||
unsigned int Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking);
|
||||
|
||||
private:
|
||||
const byte *m_alphabet;
|
||||
int m_padding, m_bitsPerChar, m_outputBlockSize;
|
||||
int m_bytePos, m_bitPos;
|
||||
SecByteBlock m_outBuf;
|
||||
};
|
||||
|
||||
class BaseN_Decoder : public Unflushable<Filter>
|
||||
{
|
||||
public:
|
||||
BaseN_Decoder(BufferedTransformation *attachment=NULL)
|
||||
: Unflushable<Filter>(attachment) {}
|
||||
|
||||
BaseN_Decoder(const int *lookup, int log2base, BufferedTransformation *attachment=NULL)
|
||||
: Unflushable<Filter>(attachment)
|
||||
{
|
||||
IsolatedInitialize(MakeParameters("DecodingLookupArray", lookup)("Log2Base", log2base));
|
||||
}
|
||||
|
||||
void IsolatedInitialize(const NameValuePairs ¶meters);
|
||||
unsigned int Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking);
|
||||
|
||||
static void InitializeDecodingLookupArray(int *lookup, const byte *alphabet, unsigned int log2base, bool caseInsensitive);
|
||||
|
||||
private:
|
||||
const int *m_lookup;
|
||||
int m_padding, m_bitsPerChar, m_outputBlockSize;
|
||||
int m_bytePos, m_bitPos;
|
||||
SecByteBlock m_outBuf;
|
||||
};
|
||||
|
||||
class Grouper : public Bufferless<Filter>
|
||||
{
|
||||
public:
|
||||
Grouper(BufferedTransformation *attachment=NULL)
|
||||
: Bufferless<Filter>(attachment) {}
|
||||
|
||||
Grouper(int groupSize, const std::string &separator, const std::string &terminator, BufferedTransformation *attachment=NULL)
|
||||
: Bufferless<Filter>(attachment)
|
||||
{
|
||||
IsolatedInitialize(MakeParameters("GroupSize", groupSize)
|
||||
("Separator", ConstByteArrayParameter(separator))
|
||||
("Terminator", ConstByteArrayParameter(terminator)));
|
||||
}
|
||||
|
||||
void IsolatedInitialize(const NameValuePairs ¶meters);
|
||||
unsigned int Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking);
|
||||
|
||||
private:
|
||||
SecByteBlock m_separator, m_terminator;
|
||||
unsigned int m_groupSize, m_counter;
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,282 @@
|
||||
// channels.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
#include "channels.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
USING_NAMESPACE(std)
|
||||
|
||||
#if 0
|
||||
void MessageSwitch::AddDefaultRoute(BufferedTransformation &destination, const std::string &channel)
|
||||
{
|
||||
m_defaultRoutes.push_back(Route(&destination, channel));
|
||||
}
|
||||
|
||||
void MessageSwitch::AddRoute(unsigned int begin, unsigned int end, BufferedTransformation &destination, const std::string &channel)
|
||||
{
|
||||
RangeRoute route(begin, end, Route(&destination, channel));
|
||||
RouteList::iterator it = upper_bound(m_routes.begin(), m_routes.end(), route);
|
||||
m_routes.insert(it, route);
|
||||
}
|
||||
|
||||
/*
|
||||
class MessageRouteIterator
|
||||
{
|
||||
public:
|
||||
typedef MessageSwitch::RouteList::const_iterator RouteIterator;
|
||||
typedef MessageSwitch::DefaultRouteList::const_iterator DefaultIterator;
|
||||
|
||||
bool m_useDefault;
|
||||
RouteIterator m_itRouteCurrent, m_itRouteEnd;
|
||||
DefaultIterator m_itDefaultCurrent, m_itDefaultEnd;
|
||||
|
||||
MessageRouteIterator(MessageSwitch &ms, const std::string &channel)
|
||||
: m_channel(channel)
|
||||
{
|
||||
pair<MapIterator, MapIterator> range = cs.m_routeMap.equal_range(channel);
|
||||
if (range.first == range.second)
|
||||
{
|
||||
m_useDefault = true;
|
||||
m_itListCurrent = cs.m_defaultRoutes.begin();
|
||||
m_itListEnd = cs.m_defaultRoutes.end();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_useDefault = false;
|
||||
m_itMapCurrent = range.first;
|
||||
m_itMapEnd = range.second;
|
||||
}
|
||||
}
|
||||
|
||||
bool End() const
|
||||
{
|
||||
return m_useDefault ? m_itListCurrent == m_itListEnd : m_itMapCurrent == m_itMapEnd;
|
||||
}
|
||||
|
||||
void Next()
|
||||
{
|
||||
if (m_useDefault)
|
||||
++m_itListCurrent;
|
||||
else
|
||||
++m_itMapCurrent;
|
||||
}
|
||||
|
||||
BufferedTransformation & Destination()
|
||||
{
|
||||
return m_useDefault ? *m_itListCurrent->first : *m_itMapCurrent->second.first;
|
||||
}
|
||||
|
||||
const std::string & Message()
|
||||
{
|
||||
if (m_useDefault)
|
||||
return m_itListCurrent->second.get() ? *m_itListCurrent->second.get() : m_channel;
|
||||
else
|
||||
return m_itMapCurrent->second.second;
|
||||
}
|
||||
};
|
||||
|
||||
void MessageSwitch::Put(byte inByte);
|
||||
void MessageSwitch::Put(const byte *inString, unsigned int length);
|
||||
|
||||
void MessageSwitch::Flush(bool completeFlush, int propagation=-1);
|
||||
void MessageSwitch::MessageEnd(int propagation=-1);
|
||||
void MessageSwitch::PutMessageEnd(const byte *inString, unsigned int length, int propagation=-1);
|
||||
void MessageSwitch::MessageSeriesEnd(int propagation=-1);
|
||||
*/
|
||||
#endif
|
||||
|
||||
class ChannelRouteIterator
|
||||
{
|
||||
public:
|
||||
typedef ChannelSwitch::RouteMap::const_iterator MapIterator;
|
||||
typedef ChannelSwitch::DefaultRouteList::const_iterator ListIterator;
|
||||
|
||||
const std::string m_channel;
|
||||
bool m_useDefault;
|
||||
MapIterator m_itMapCurrent, m_itMapEnd;
|
||||
ListIterator m_itListCurrent, m_itListEnd;
|
||||
|
||||
ChannelRouteIterator(ChannelSwitch &cs, const std::string &channel)
|
||||
: m_channel(channel)
|
||||
{
|
||||
pair<MapIterator, MapIterator> range = cs.m_routeMap.equal_range(channel);
|
||||
if (range.first == range.second)
|
||||
{
|
||||
m_useDefault = true;
|
||||
m_itListCurrent = cs.m_defaultRoutes.begin();
|
||||
m_itListEnd = cs.m_defaultRoutes.end();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_useDefault = false;
|
||||
m_itMapCurrent = range.first;
|
||||
m_itMapEnd = range.second;
|
||||
}
|
||||
}
|
||||
|
||||
bool End() const
|
||||
{
|
||||
return m_useDefault ? m_itListCurrent == m_itListEnd : m_itMapCurrent == m_itMapEnd;
|
||||
}
|
||||
|
||||
void Next()
|
||||
{
|
||||
if (m_useDefault)
|
||||
++m_itListCurrent;
|
||||
else
|
||||
++m_itMapCurrent;
|
||||
}
|
||||
|
||||
BufferedTransformation & Destination()
|
||||
{
|
||||
return m_useDefault ? *m_itListCurrent->first : *m_itMapCurrent->second.first;
|
||||
}
|
||||
|
||||
const std::string & Channel()
|
||||
{
|
||||
if (m_useDefault)
|
||||
return m_itListCurrent->second.get() ? *m_itListCurrent->second.get() : m_channel;
|
||||
else
|
||||
return m_itMapCurrent->second.second;
|
||||
}
|
||||
};
|
||||
|
||||
unsigned int ChannelSwitch::ChannelPut2(const std::string &channel, const byte *begin, unsigned int length, int messageEnd, bool blocking)
|
||||
{
|
||||
if (!blocking)
|
||||
throw BlockingInputOnly("ChannelSwitch");
|
||||
|
||||
ChannelRouteIterator it(*this, channel);
|
||||
while (!it.End())
|
||||
{
|
||||
it.Destination().ChannelPut2(it.Channel(), begin, length, messageEnd, blocking);
|
||||
it.Next();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ChannelSwitch::ChannelInitialize(const std::string &channel, const NameValuePairs ¶meters/* =g_nullNameValuePairs */, int propagation/* =-1 */)
|
||||
{
|
||||
if (channel.empty())
|
||||
{
|
||||
m_routeMap.clear();
|
||||
m_defaultRoutes.clear();
|
||||
}
|
||||
|
||||
ChannelRouteIterator it(*this, channel);
|
||||
while (!it.End())
|
||||
{
|
||||
it.Destination().ChannelInitialize(it.Channel(), parameters, propagation);
|
||||
it.Next();
|
||||
}
|
||||
}
|
||||
|
||||
bool ChannelSwitch::ChannelFlush(const std::string &channel, bool completeFlush, int propagation, bool blocking)
|
||||
{
|
||||
if (!blocking)
|
||||
throw BlockingInputOnly("ChannelSwitch");
|
||||
|
||||
ChannelRouteIterator it(*this, channel);
|
||||
while (!it.End())
|
||||
{
|
||||
it.Destination().ChannelFlush(it.Channel(), completeFlush, propagation, blocking);
|
||||
it.Next();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ChannelSwitch::ChannelMessageSeriesEnd(const std::string &channel, int propagation, bool blocking)
|
||||
{
|
||||
if (!blocking)
|
||||
throw BlockingInputOnly("ChannelSwitch");
|
||||
|
||||
ChannelRouteIterator it(*this, channel);
|
||||
while (!it.End())
|
||||
{
|
||||
it.Destination().ChannelMessageSeriesEnd(it.Channel(), propagation);
|
||||
it.Next();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
byte * ChannelSwitch::ChannelCreatePutSpace(const std::string &channel, unsigned int &size)
|
||||
{
|
||||
ChannelRouteIterator it(*this, channel);
|
||||
if (!it.End())
|
||||
{
|
||||
BufferedTransformation &target = it.Destination();
|
||||
it.Next();
|
||||
if (it.End()) // there is only one target channel
|
||||
return target.ChannelCreatePutSpace(it.Channel(), size);
|
||||
}
|
||||
size = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
unsigned int ChannelSwitch::ChannelPutModifiable2(const std::string &channel, byte *inString, unsigned int length, int messageEnd, bool blocking)
|
||||
{
|
||||
if (!blocking)
|
||||
throw BlockingInputOnly("ChannelSwitch");
|
||||
|
||||
ChannelRouteIterator it(*this, channel);
|
||||
if (!it.End())
|
||||
{
|
||||
BufferedTransformation &target = it.Destination();
|
||||
const std::string &targetChannel = it.Channel();
|
||||
it.Next();
|
||||
if (it.End()) // there is only one target channel
|
||||
return target.ChannelPutModifiable2(targetChannel, inString, length, messageEnd, blocking);
|
||||
}
|
||||
ChannelPut2(channel, inString, length, messageEnd, blocking);
|
||||
return false;
|
||||
}
|
||||
|
||||
void ChannelSwitch::AddDefaultRoute(BufferedTransformation &destination)
|
||||
{
|
||||
m_defaultRoutes.push_back(DefaultRoute(&destination, value_ptr<std::string>(NULL)));
|
||||
}
|
||||
|
||||
void ChannelSwitch::RemoveDefaultRoute(BufferedTransformation &destination)
|
||||
{
|
||||
for (DefaultRouteList::iterator it = m_defaultRoutes.begin(); it != m_defaultRoutes.end(); ++it)
|
||||
if (it->first == &destination && !it->second.get())
|
||||
{
|
||||
m_defaultRoutes.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ChannelSwitch::AddDefaultRoute(BufferedTransformation &destination, const std::string &outChannel)
|
||||
{
|
||||
m_defaultRoutes.push_back(DefaultRoute(&destination, outChannel));
|
||||
}
|
||||
|
||||
void ChannelSwitch::RemoveDefaultRoute(BufferedTransformation &destination, const std::string &outChannel)
|
||||
{
|
||||
for (DefaultRouteList::iterator it = m_defaultRoutes.begin(); it != m_defaultRoutes.end(); ++it)
|
||||
if (it->first == &destination && (it->second.get() && *it->second == outChannel))
|
||||
{
|
||||
m_defaultRoutes.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ChannelSwitch::AddRoute(const std::string &inChannel, BufferedTransformation &destination, const std::string &outChannel)
|
||||
{
|
||||
m_routeMap.insert(RouteMap::value_type(inChannel, Route(&destination, outChannel)));
|
||||
}
|
||||
|
||||
void ChannelSwitch::RemoveRoute(const std::string &inChannel, BufferedTransformation &destination, const std::string &outChannel)
|
||||
{
|
||||
typedef ChannelSwitch::RouteMap::iterator MapIterator;
|
||||
pair<MapIterator, MapIterator> range = m_routeMap.equal_range(inChannel);
|
||||
|
||||
for (MapIterator it = range.first; it != range.second; ++it)
|
||||
if (it->second.first == &destination && it->second.second == outChannel)
|
||||
{
|
||||
m_routeMap.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -0,0 +1,91 @@
|
||||
#ifndef CRYPTOPP_CHANNELS_H
|
||||
#define CRYPTOPP_CHANNELS_H
|
||||
|
||||
#include "simple.h"
|
||||
#include "smartptr.h"
|
||||
#include <map>
|
||||
#include <list>
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
#if 0
|
||||
//! Route input on default channel to different and/or multiple channels based on message sequence number
|
||||
class MessageSwitch : public Sink
|
||||
{
|
||||
public:
|
||||
void AddDefaultRoute(BufferedTransformation &destination, const std::string &channel);
|
||||
void AddRoute(unsigned int begin, unsigned int end, BufferedTransformation &destination, const std::string &channel);
|
||||
|
||||
void Put(byte inByte);
|
||||
void Put(const byte *inString, unsigned int length);
|
||||
|
||||
void Flush(bool completeFlush, int propagation=-1);
|
||||
void MessageEnd(int propagation=-1);
|
||||
void PutMessageEnd(const byte *inString, unsigned int length, int propagation=-1);
|
||||
void MessageSeriesEnd(int propagation=-1);
|
||||
|
||||
private:
|
||||
typedef std::pair<BufferedTransformation *, std::string> Route;
|
||||
struct RangeRoute
|
||||
{
|
||||
RangeRoute(unsigned int begin, unsigned int end, const Route &route)
|
||||
: begin(begin), end(end), route(route) {}
|
||||
bool operator<(const RangeRoute &rhs) const {return begin < rhs.begin;}
|
||||
unsigned int begin, end;
|
||||
Route route;
|
||||
};
|
||||
|
||||
typedef std::list<RangeRoute> RouteList;
|
||||
typedef std::list<Route> DefaultRouteList;
|
||||
|
||||
RouteList m_routes;
|
||||
DefaultRouteList m_defaultRoutes;
|
||||
unsigned int m_nCurrentMessage;
|
||||
};
|
||||
#endif
|
||||
|
||||
//! Route input to different and/or multiple channels based on channel ID
|
||||
class ChannelSwitch : public Multichannel<Sink>
|
||||
{
|
||||
public:
|
||||
ChannelSwitch() {}
|
||||
ChannelSwitch(BufferedTransformation &destination)
|
||||
{
|
||||
AddDefaultRoute(destination);
|
||||
}
|
||||
ChannelSwitch(BufferedTransformation &destination, const std::string &outChannel)
|
||||
{
|
||||
AddDefaultRoute(destination, outChannel);
|
||||
}
|
||||
|
||||
unsigned int ChannelPut2(const std::string &channel, const byte *begin, unsigned int length, int messageEnd, bool blocking);
|
||||
unsigned int ChannelPutModifiable2(const std::string &channel, byte *begin, unsigned int length, int messageEnd, bool blocking);
|
||||
|
||||
void ChannelInitialize(const std::string &channel, const NameValuePairs ¶meters=g_nullNameValuePairs, int propagation=-1);
|
||||
bool ChannelFlush(const std::string &channel, bool completeFlush, int propagation=-1, bool blocking=true);
|
||||
bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true);
|
||||
|
||||
byte * ChannelCreatePutSpace(const std::string &channel, unsigned int &size);
|
||||
|
||||
void AddDefaultRoute(BufferedTransformation &destination);
|
||||
void RemoveDefaultRoute(BufferedTransformation &destination);
|
||||
void AddDefaultRoute(BufferedTransformation &destination, const std::string &outChannel);
|
||||
void RemoveDefaultRoute(BufferedTransformation &destination, const std::string &outChannel);
|
||||
void AddRoute(const std::string &inChannel, BufferedTransformation &destination, const std::string &outChannel);
|
||||
void RemoveRoute(const std::string &inChannel, BufferedTransformation &destination, const std::string &outChannel);
|
||||
|
||||
private:
|
||||
typedef std::pair<BufferedTransformation *, std::string> Route;
|
||||
typedef std::multimap<std::string, Route> RouteMap;
|
||||
RouteMap m_routeMap;
|
||||
|
||||
typedef std::pair<BufferedTransformation *, value_ptr<std::string> > DefaultRoute;
|
||||
typedef std::list<DefaultRoute> DefaultRouteList;
|
||||
DefaultRouteList m_defaultRoutes;
|
||||
|
||||
friend class ChannelRouteIterator;
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,247 @@
|
||||
#ifndef CRYPTOPP_CONFIG_H
|
||||
#define CRYPTOPP_CONFIG_H
|
||||
|
||||
// ***************** Important Settings ********************
|
||||
|
||||
// define this if running on a big-endian CPU
|
||||
#if !defined(IS_LITTLE_ENDIAN) && (defined(__BIG_ENDIAN__) || defined(__sparc) || defined(__sparc__) || defined(__hppa__) || 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 to 1 to enforce the requirement in FIPS 186-2 Change Notice 1 that only 1024 bit moduli be used
|
||||
#ifndef DSA_1024_BIT_MODULUS_ONLY
|
||||
# define DSA_1024_BIT_MODULUS_ONLY 1
|
||||
#endif
|
||||
|
||||
// ***************** Less Important Settings ***************
|
||||
|
||||
// define this to retain (as much as possible) old deprecated function and class names
|
||||
// #define CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
|
||||
|
||||
#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.
|
||||
|
||||
// namespace support is now required
|
||||
#ifdef NO_NAMESPACE
|
||||
# error namespace support is now required
|
||||
#endif
|
||||
|
||||
// Define this to workaround a Microsoft CryptoAPI bug where
|
||||
// each call to CryptAcquireContext causes a 100 KB memory leak.
|
||||
// Defining this will cause Crypto++ to make only one call to CryptAcquireContext.
|
||||
#define WORKAROUND_MS_BUG_Q258000
|
||||
|
||||
// Avoid putting "CryptoPP::" in front of everything in Doxygen output
|
||||
#ifdef CRYPTOPP_DOXYGEN_PROCESSING
|
||||
# define CryptoPP
|
||||
# define NAMESPACE_BEGIN(x)
|
||||
# define NAMESPACE_END
|
||||
#else
|
||||
# define NAMESPACE_BEGIN(x) namespace x {
|
||||
# define NAMESPACE_END }
|
||||
#endif
|
||||
#define ANONYMOUS_NAMESPACE_BEGIN namespace {
|
||||
#define USING_NAMESPACE(x) using namespace x;
|
||||
#define DOCUMENTED_NAMESPACE_BEGIN(x) namespace x {
|
||||
#define DOCUMENTED_NAMESPACE_END }
|
||||
|
||||
// What is the type of the third parameter to bind?
|
||||
// For Unix, the new standard is ::socklen_t (typically unsigned int), and the old standard is int.
|
||||
// Unfortunately there is no way to tell whether or not socklen_t is defined.
|
||||
// To work around this, TYPE_OF_SOCKLEN_T is a macro so that you can change it from the makefile.
|
||||
#ifndef TYPE_OF_SOCKLEN_T
|
||||
# if defined(_WIN32) || defined(__CYGWIN__) || defined(__MACH__)
|
||||
# define TYPE_OF_SOCKLEN_T int
|
||||
# else
|
||||
# define TYPE_OF_SOCKLEN_T ::socklen_t
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(__CYGWIN__) && defined(PREFER_WINDOWS_STYLE_SOCKETS)
|
||||
# define __USE_W32_SOCKETS
|
||||
#endif
|
||||
|
||||
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
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
// VC60 workaround: it doesn't allow typename in some places
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1300)
|
||||
#define CPP_TYPENAME
|
||||
#else
|
||||
#define CPP_TYPENAME typename
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// 4250: dominance
|
||||
// 4660: explicitly instantiating a class that's already implicitly instantiated
|
||||
// 4661: no suitable definition provided for explicit template instantiation request
|
||||
// 4786: identifer was truncated in debug information
|
||||
// 4355: 'this' : used in base member initializer list
|
||||
# pragma warning(disable: 4250 4660 4661 4786 4355)
|
||||
#endif
|
||||
|
||||
// ***************** determine availability of OS features ********************
|
||||
|
||||
#ifndef NO_OS_DEPENDENCE
|
||||
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
#define CRYPTOPP_WIN32_AVAILABLE
|
||||
#endif
|
||||
|
||||
#if defined(__unix__) || defined(__MACH__)
|
||||
#define CRYPTOPP_UNIX_AVAILABLE
|
||||
#endif
|
||||
|
||||
#if defined(WORD64_AVAILABLE) && (defined(CRYPTOPP_WIN32_AVAILABLE) || defined(CRYPTOPP_UNIX_AVAILABLE) || defined(macintosh))
|
||||
# define HIGHRES_TIMER_AVAILABLE
|
||||
#endif
|
||||
|
||||
#ifdef CRYPTOPP_UNIX_AVAILABLE
|
||||
# define HAS_BERKELEY_STYLE_SOCKETS
|
||||
#endif
|
||||
|
||||
#ifdef CRYPTOPP_WIN32_AVAILABLE
|
||||
# define HAS_WINDOWS_STYLE_SOCKETS
|
||||
#endif
|
||||
|
||||
#if defined(HIGHRES_TIMER_AVAILABLE) && (defined(HAS_BERKELEY_STYLE_SOCKETS) || defined(HAS_WINDOWS_STYLE_SOCKETS))
|
||||
# define SOCKETS_AVAILABLE
|
||||
#endif
|
||||
|
||||
#if defined(HAS_WINDOWS_STYLE_SOCKETS) && (!defined(HAS_BERKELEY_STYLE_SOCKETS) || defined(PREFER_WINDOWS_STYLE_SOCKETS))
|
||||
# define USE_WINDOWS_STYLE_SOCKETS
|
||||
#else
|
||||
# define USE_BERKELEY_STYLE_SOCKETS
|
||||
#endif
|
||||
|
||||
#if defined(CRYPTOPP_WIN32_AVAILABLE) && !defined(USE_BERKELEY_STYLE_SOCKETS)
|
||||
# define WINDOWS_PIPES_AVAILABLE
|
||||
#endif
|
||||
|
||||
#if defined(CRYPTOPP_WIN32_AVAILABLE) && defined(USE_MS_CRYPTOAPI)
|
||||
# define NONBLOCKING_RNG_AVAILABLE
|
||||
# define OS_RNG_AVAILABLE
|
||||
#endif
|
||||
|
||||
#ifdef CRYPTOPP_UNIX_AVAILABLE
|
||||
# define NONBLOCKING_RNG_AVAILABLE
|
||||
# define BLOCKING_RNG_AVAILABLE
|
||||
# define OS_RNG_AVAILABLE
|
||||
# define HAS_PTHREADS
|
||||
# define THREADS_AVAILABLE
|
||||
#endif
|
||||
|
||||
#ifdef CRYPTOPP_WIN32_AVAILABLE
|
||||
# define HAS_WINTHREADS
|
||||
# define THREADS_AVAILABLE
|
||||
#endif
|
||||
|
||||
#endif // NO_OS_DEPENDENCE
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,388 @@
|
||||
# Microsoft Developer Studio Project File - Name="cryptest" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 60000
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
CFG=cryptest - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "cryptest.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "cryptest.mak" CFG="cryptest - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "cryptest - Win32 FIPS 140 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "cryptest - Win32 FIPS 140 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "cryptest - Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "cryptest - Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "cryptest - Win32 FIPS 140 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "cryptest___Win32_FIPS_140_Release"
|
||||
# PROP BASE Intermediate_Dir "cryptest___Win32_FIPS_140_Release"
|
||||
# PROP BASE Ignore_Export_Lib 0
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "CT_FIPS_140_Release"
|
||||
# PROP Intermediate_Dir "CT_FIPS_140_Release"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /G5 /Gz /MT /W3 /GX /Zi /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /Zm200 /c
|
||||
# ADD CPP /nologo /G5 /Gz /MT /W3 /GX /Zi /O2 /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "WIN32" /YX /FD /Zm200 /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /OPT:NOWIN98
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /OPT:NOWIN98
|
||||
# Begin Special Build Tool
|
||||
SOURCE="$(InputPath)"
|
||||
PostBuild_Cmds=echo This configuration is used to build a static binary for FIPS 140 evaluation by a testing laboratory. echo Crypto++ users should not build this configuration directly.
|
||||
# End Special Build Tool
|
||||
|
||||
!ELSEIF "$(CFG)" == "cryptest - Win32 FIPS 140 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "cryptest___Win32_FIPS_140_Debug"
|
||||
# PROP BASE Intermediate_Dir "cryptest___Win32_FIPS_140_Debug"
|
||||
# PROP BASE Ignore_Export_Lib 0
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "CT_FIPS_140_Debug"
|
||||
# PROP Intermediate_Dir "CT_FIPS_140_Debug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MTd /W3 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /Zm200 /c
|
||||
# ADD CPP /nologo /G5 /Gz /MTd /W3 /GX /ZI /Od /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "WIN32" /YX /FD /Zm200 /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /OPT:NOWIN98
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /OPT:NOWIN98
|
||||
# Begin Special Build Tool
|
||||
SOURCE="$(InputPath)"
|
||||
PostBuild_Cmds=echo This configuration is used to build a static binary for FIPS 140 evaluation by a testing laboratory. echo Crypto++ users should not build this configuration directly.
|
||||
# End Special Build Tool
|
||||
|
||||
!ELSEIF "$(CFG)" == "cryptest - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "cryptes0"
|
||||
# PROP BASE Intermediate_Dir "cryptes0"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "CTRelease"
|
||||
# PROP Intermediate_Dir "CTRelease"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /Zi /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /Zm200 /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /OPT:NOWIN98
|
||||
|
||||
!ELSEIF "$(CFG)" == "cryptest - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "cryptes1"
|
||||
# PROP BASE Intermediate_Dir "cryptes1"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "CTDebug"
|
||||
# PROP Intermediate_Dir "CTDebug"
|
||||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /MDd /W3 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /Zm200 /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Ws2_32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /OPT:NOWIN98
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "cryptest - Win32 FIPS 140 Release"
|
||||
# Name "cryptest - Win32 FIPS 140 Debug"
|
||||
# Name "cryptest - Win32 Release"
|
||||
# Name "cryptest - Win32 Debug"
|
||||
# Begin Group "Test Data"
|
||||
|
||||
# PROP Default_Filter ".dat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\3desval.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\3wayval.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cast128v.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cast256v.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\descert.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\dh1024.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\dh2048.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\diamond.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\digest.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\dsa1024.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\dsa1024b.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\dsa512.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\elgc1024.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\esig1023.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\esig1536.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\esig2046.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gostval.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\havalcer.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ideaval.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\luc1024.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\luc2048.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\lucc1024.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\lucc512.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\lucd1024.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\lucd512.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\lucs1024.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\lucs512.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\marsval.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\mqv1024.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\mqv2048.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\nr1024.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\nr2048.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\rabi1024.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\rabi2048.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\rc2val.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\rc5val.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\rc6val.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\rijndael.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\rsa1024.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\rsa2048.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\rsa400pb.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\rsa400pv.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\rsa512a.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\rw1024.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\rw2048.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\saferval.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\serpentv.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\sharkval.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\skipjack.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\squareva.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\twofishv.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\usage.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\xtrdh171.dat
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\xtrdh342.dat
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Source Code"
|
||||
|
||||
# PROP Default_Filter ".cpp;.h"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\bench.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\factory.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\test.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\validate.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
@@ -0,0 +1,44 @@
|
||||
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "cryptest"=.\cryptest.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
Begin Project Dependency
|
||||
Project_Dep_Name cryptlib
|
||||
End Project Dependency
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "cryptlib"=.\cryptlib.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Global:
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<3>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
@@ -0,0 +1,687 @@
|
||||
// cryptlib.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
#include "cryptlib.h"
|
||||
#include "misc.h"
|
||||
#include "filters.h"
|
||||
#include "algparam.h"
|
||||
#include "fips140.h"
|
||||
#include "argnames.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
CRYPTOPP_COMPILE_ASSERT(sizeof(byte) == 1);
|
||||
CRYPTOPP_COMPILE_ASSERT(sizeof(word16) == 2);
|
||||
CRYPTOPP_COMPILE_ASSERT(sizeof(word32) == 4);
|
||||
#ifdef WORD64_AVAILABLE
|
||||
CRYPTOPP_COMPILE_ASSERT(sizeof(word64) == 8);
|
||||
#endif
|
||||
CRYPTOPP_COMPILE_ASSERT(sizeof(dword) == 2*sizeof(word));
|
||||
|
||||
const std::string BufferedTransformation::NULL_CHANNEL;
|
||||
const NullNameValuePairs g_nullNameValuePairs;
|
||||
|
||||
BufferedTransformation & TheBitBucket()
|
||||
{
|
||||
static BitBucket bitBucket;
|
||||
return bitBucket;
|
||||
}
|
||||
|
||||
Algorithm::Algorithm(bool checkSelfTestStatus)
|
||||
{
|
||||
if (checkSelfTestStatus && FIPS_140_2_ComplianceEnabled())
|
||||
{
|
||||
if (GetPowerUpSelfTestStatus() == POWER_UP_SELF_TEST_NOT_DONE && !PowerUpSelfTestInProgressOnThisThread())
|
||||
throw SelfTestFailure("Cryptographic algorithms are disabled before the power-up self tests are performed.");
|
||||
|
||||
if (GetPowerUpSelfTestStatus() == POWER_UP_SELF_TEST_FAILED)
|
||||
throw SelfTestFailure("Cryptographic algorithms are disabled after power-up a self test failed.");
|
||||
}
|
||||
}
|
||||
|
||||
void SimpleKeyingInterface::SetKeyWithRounds(const byte *key, unsigned int length, int rounds)
|
||||
{
|
||||
SetKey(key, length, MakeParameters(Name::Rounds(), rounds));
|
||||
}
|
||||
|
||||
void SimpleKeyingInterface::SetKeyWithIV(const byte *key, unsigned int length, const byte *iv)
|
||||
{
|
||||
SetKey(key, length, MakeParameters(Name::IV(), iv));
|
||||
}
|
||||
|
||||
void SimpleKeyingInterface::ThrowIfInvalidKeyLength(const Algorithm &algorithm, unsigned int length)
|
||||
{
|
||||
if (!IsValidKeyLength(length))
|
||||
throw InvalidKeyLength(algorithm.AlgorithmName(), length);
|
||||
}
|
||||
|
||||
void BlockTransformation::ProcessAndXorMultipleBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, unsigned int numberOfBlocks) const
|
||||
{
|
||||
unsigned int blockSize = BlockSize();
|
||||
while (numberOfBlocks--)
|
||||
{
|
||||
ProcessAndXorBlock(inBlocks, xorBlocks, outBlocks);
|
||||
inBlocks += blockSize;
|
||||
outBlocks += blockSize;
|
||||
if (xorBlocks)
|
||||
xorBlocks += blockSize;
|
||||
}
|
||||
}
|
||||
|
||||
void StreamTransformation::ProcessLastBlock(byte *outString, const byte *inString, unsigned int length)
|
||||
{
|
||||
assert(MinLastBlockSize() == 0); // this function should be overriden otherwise
|
||||
|
||||
if (length == MandatoryBlockSize())
|
||||
ProcessData(outString, inString, length);
|
||||
else if (length != 0)
|
||||
throw NotImplemented("StreamTransformation: this object does't support a special last block");
|
||||
}
|
||||
|
||||
unsigned int RandomNumberGenerator::GenerateBit()
|
||||
{
|
||||
return Parity(GenerateByte());
|
||||
}
|
||||
|
||||
void RandomNumberGenerator::GenerateBlock(byte *output, unsigned int size)
|
||||
{
|
||||
while (size--)
|
||||
*output++ = GenerateByte();
|
||||
}
|
||||
|
||||
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) | GenerateByte();
|
||||
|
||||
value = Crop(value, maxBits);
|
||||
} while (value > range);
|
||||
|
||||
return value+min;
|
||||
}
|
||||
|
||||
void RandomNumberGenerator::DiscardBytes(unsigned int n)
|
||||
{
|
||||
while (n--)
|
||||
GenerateByte();
|
||||
}
|
||||
|
||||
RandomNumberGenerator & NullRNG()
|
||||
{
|
||||
class NullRNG : public RandomNumberGenerator
|
||||
{
|
||||
public:
|
||||
std::string AlgorithmName() const {return "NullRNG";}
|
||||
byte GenerateByte() {throw NotImplemented("NullRNG: NullRNG should only be passed to functions that don't need to generate random bytes");}
|
||||
};
|
||||
|
||||
static NullRNG s_nullRNG;
|
||||
return s_nullRNG;
|
||||
}
|
||||
|
||||
bool HashTransformation::TruncatedVerify(const byte *digestIn, unsigned int digestLength)
|
||||
{
|
||||
ThrowIfInvalidTruncatedSize(digestLength);
|
||||
SecByteBlock digest(digestLength);
|
||||
TruncatedFinal(digest, digestLength);
|
||||
return memcmp(digest, digestIn, digestLength) == 0;
|
||||
}
|
||||
|
||||
void HashTransformation::ThrowIfInvalidTruncatedSize(unsigned int size) const
|
||||
{
|
||||
if (size > DigestSize())
|
||||
throw InvalidArgument("HashTransformation: can't truncate a " + IntToString(DigestSize()) + " byte digest to " + IntToString(size) + " bytes");
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::GetMaxWaitObjectCount() const
|
||||
{
|
||||
const BufferedTransformation *t = AttachedTransformation();
|
||||
return t ? t->GetMaxWaitObjectCount() : 0;
|
||||
}
|
||||
|
||||
void BufferedTransformation::GetWaitObjects(WaitObjectContainer &container)
|
||||
{
|
||||
BufferedTransformation *t = AttachedTransformation();
|
||||
if (t)
|
||||
t->GetWaitObjects(container);
|
||||
}
|
||||
|
||||
void BufferedTransformation::Initialize(const NameValuePairs ¶meters, int propagation)
|
||||
{
|
||||
assert(!AttachedTransformation());
|
||||
IsolatedInitialize(parameters);
|
||||
}
|
||||
|
||||
bool BufferedTransformation::Flush(bool hardFlush, int propagation, bool blocking)
|
||||
{
|
||||
assert(!AttachedTransformation());
|
||||
return IsolatedFlush(hardFlush, blocking);
|
||||
}
|
||||
|
||||
bool BufferedTransformation::MessageSeriesEnd(int propagation, bool blocking)
|
||||
{
|
||||
assert(!AttachedTransformation());
|
||||
return IsolatedMessageSeriesEnd(blocking);
|
||||
}
|
||||
|
||||
byte * BufferedTransformation::ChannelCreatePutSpace(const std::string &channel, unsigned int &size)
|
||||
{
|
||||
if (channel.empty())
|
||||
return CreatePutSpace(size);
|
||||
else
|
||||
throw NoChannelSupport();
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::ChannelPut2(const std::string &channel, const byte *begin, unsigned int length, int messageEnd, bool blocking)
|
||||
{
|
||||
if (channel.empty())
|
||||
return Put2(begin, length, messageEnd, blocking);
|
||||
else
|
||||
throw NoChannelSupport();
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::ChannelPutModifiable2(const std::string &channel, byte *begin, unsigned int length, int messageEnd, bool blocking)
|
||||
{
|
||||
if (channel.empty())
|
||||
return PutModifiable2(begin, length, messageEnd, blocking);
|
||||
else
|
||||
return ChannelPut2(channel, begin, length, messageEnd, blocking);
|
||||
}
|
||||
|
||||
void BufferedTransformation::ChannelInitialize(const std::string &channel, const NameValuePairs ¶meters, int propagation)
|
||||
{
|
||||
if (channel.empty())
|
||||
Initialize(parameters, propagation);
|
||||
else
|
||||
throw NoChannelSupport();
|
||||
}
|
||||
|
||||
bool BufferedTransformation::ChannelFlush(const std::string &channel, bool completeFlush, int propagation, bool blocking)
|
||||
{
|
||||
if (channel.empty())
|
||||
return Flush(completeFlush, propagation, blocking);
|
||||
else
|
||||
throw NoChannelSupport();
|
||||
}
|
||||
|
||||
bool BufferedTransformation::ChannelMessageSeriesEnd(const std::string &channel, int propagation, bool blocking)
|
||||
{
|
||||
if (channel.empty())
|
||||
return MessageSeriesEnd(propagation, blocking);
|
||||
else
|
||||
throw NoChannelSupport();
|
||||
}
|
||||
|
||||
unsigned long BufferedTransformation::MaxRetrievable() const
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->MaxRetrievable();
|
||||
else
|
||||
return CopyTo(TheBitBucket());
|
||||
}
|
||||
|
||||
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(TheBitBucket(), skipMax);
|
||||
}
|
||||
|
||||
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(TheBitBucket());
|
||||
}
|
||||
|
||||
bool BufferedTransformation::AnyMessages() const
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->AnyMessages();
|
||||
else
|
||||
return NumberOfMessages() != 0;
|
||||
}
|
||||
|
||||
bool BufferedTransformation::GetNextMessage()
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->GetNextMessage();
|
||||
else
|
||||
{
|
||||
assert(!AnyMessages());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::SkipMessages(unsigned int count)
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->SkipMessages(count);
|
||||
else
|
||||
return TransferMessagesTo(TheBitBucket(), count);
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::TransferMessagesTo2(BufferedTransformation &target, unsigned int &messageCount, const std::string &channel, bool blocking)
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->TransferMessagesTo2(target, messageCount, channel, blocking);
|
||||
else
|
||||
{
|
||||
unsigned int maxMessages = messageCount;
|
||||
for (messageCount=0; messageCount < maxMessages && AnyMessages(); messageCount++)
|
||||
{
|
||||
unsigned int blockedBytes;
|
||||
unsigned long transferedBytes;
|
||||
|
||||
while (AnyRetrievable())
|
||||
{
|
||||
transferedBytes = ULONG_MAX;
|
||||
blockedBytes = TransferTo2(target, transferedBytes, channel, blocking);
|
||||
if (blockedBytes > 0)
|
||||
return blockedBytes;
|
||||
}
|
||||
|
||||
if (target.ChannelMessageEnd(channel, GetAutoSignalPropagation(), blocking))
|
||||
return 1;
|
||||
|
||||
bool result = GetNextMessage();
|
||||
assert(result);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::CopyMessagesTo(BufferedTransformation &target, unsigned int count, const std::string &channel) const
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->CopyMessagesTo(target, count, channel);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void BufferedTransformation::SkipAll()
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
AttachedTransformation()->SkipAll();
|
||||
else
|
||||
{
|
||||
while (SkipMessages()) {}
|
||||
while (Skip()) {}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::TransferAllTo2(BufferedTransformation &target, const std::string &channel, bool blocking)
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->TransferAllTo2(target, channel, blocking);
|
||||
else
|
||||
{
|
||||
assert(!NumberOfMessageSeries());
|
||||
|
||||
unsigned int messageCount;
|
||||
do
|
||||
{
|
||||
messageCount = UINT_MAX;
|
||||
unsigned int blockedBytes = TransferMessagesTo2(target, messageCount, channel, blocking);
|
||||
if (blockedBytes)
|
||||
return blockedBytes;
|
||||
}
|
||||
while (messageCount != 0);
|
||||
|
||||
unsigned long byteCount;
|
||||
do
|
||||
{
|
||||
byteCount = ULONG_MAX;
|
||||
unsigned int blockedBytes = TransferTo2(target, byteCount, channel, blocking);
|
||||
if (blockedBytes)
|
||||
return blockedBytes;
|
||||
}
|
||||
while (byteCount != 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void BufferedTransformation::CopyAllTo(BufferedTransformation &target, const std::string &channel) const
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
AttachedTransformation()->CopyAllTo(target, channel);
|
||||
else
|
||||
{
|
||||
assert(!NumberOfMessageSeries());
|
||||
while (CopyMessagesTo(target, UINT_MAX, channel)) {}
|
||||
}
|
||||
}
|
||||
|
||||
void BufferedTransformation::SetRetrievalChannel(const std::string &channel)
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
AttachedTransformation()->SetRetrievalChannel(channel);
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::ChannelPutWord16(const std::string &channel, word16 value, ByteOrder order, bool blocking)
|
||||
{
|
||||
FixedSizeSecBlock<byte, 2> buf;
|
||||
PutWord(false, order, buf, value);
|
||||
return ChannelPut(channel, buf, 2, blocking);
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::ChannelPutWord32(const std::string &channel, word32 value, ByteOrder order, bool blocking)
|
||||
{
|
||||
FixedSizeSecBlock<byte, 4> buf;
|
||||
PutWord(false, order, buf, value);
|
||||
return ChannelPut(channel, buf, 4, blocking);
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::PutWord16(word16 value, ByteOrder order, bool blocking)
|
||||
{
|
||||
return ChannelPutWord16(NULL_CHANNEL, value, order, blocking);
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::PutWord32(word32 value, ByteOrder order, bool blocking)
|
||||
{
|
||||
return ChannelPutWord32(NULL_CHANNEL, value, order, blocking);
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::PeekWord16(word16 &value, ByteOrder order)
|
||||
{
|
||||
byte buf[2] = {0, 0};
|
||||
unsigned int len = Peek(buf, 2);
|
||||
|
||||
if (order)
|
||||
value = (buf[0] << 8) | buf[1];
|
||||
else
|
||||
value = (buf[1] << 8) | buf[0];
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::PeekWord32(word32 &value, ByteOrder order)
|
||||
{
|
||||
byte buf[4] = {0, 0, 0, 0};
|
||||
unsigned int len = Peek(buf, 4);
|
||||
|
||||
if (order)
|
||||
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, ByteOrder order)
|
||||
{
|
||||
return Skip(PeekWord16(value, order));
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::GetWord32(word32 &value, ByteOrder order)
|
||||
{
|
||||
return Skip(PeekWord32(value, order));
|
||||
}
|
||||
|
||||
void BufferedTransformation::Attach(BufferedTransformation *newOut)
|
||||
{
|
||||
if (AttachedTransformation() && AttachedTransformation()->Attachable())
|
||||
AttachedTransformation()->Attach(newOut);
|
||||
else
|
||||
Detach(newOut);
|
||||
}
|
||||
|
||||
void GeneratableCryptoMaterial::GenerateRandomWithKeySize(RandomNumberGenerator &rng, unsigned int keySize)
|
||||
{
|
||||
GenerateRandom(rng, MakeParameters("KeySize", (int)keySize));
|
||||
}
|
||||
|
||||
BufferedTransformation * PK_Encryptor::CreateEncryptionFilter(RandomNumberGenerator &rng, BufferedTransformation *attachment) const
|
||||
{
|
||||
struct EncryptionFilter : public Unflushable<FilterWithInputQueue>
|
||||
{
|
||||
// VC60 complains if this function is missing
|
||||
EncryptionFilter(const EncryptionFilter &x) : Unflushable<FilterWithInputQueue>(NULL), m_rng(x.m_rng), m_encryptor(x.m_encryptor) {}
|
||||
|
||||
EncryptionFilter(RandomNumberGenerator &rng, const PK_Encryptor &encryptor, BufferedTransformation *attachment)
|
||||
: Unflushable<FilterWithInputQueue>(attachment), m_rng(rng), m_encryptor(encryptor)
|
||||
{
|
||||
}
|
||||
|
||||
bool IsolatedMessageEnd(bool blocking)
|
||||
{
|
||||
switch (m_continueAt)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
unsigned int plaintextLength = m_inQueue.CurrentSize();
|
||||
m_ciphertextLength = m_encryptor.CiphertextLength(plaintextLength);
|
||||
|
||||
SecByteBlock plaintext(plaintextLength);
|
||||
m_inQueue.Get(plaintext, plaintextLength);
|
||||
m_ciphertext.resize(m_ciphertextLength);
|
||||
m_encryptor.Encrypt(m_rng, plaintext, plaintextLength, m_ciphertext);
|
||||
}
|
||||
|
||||
case 1:
|
||||
if (!Output(1, m_ciphertext, m_ciphertextLength, 0, blocking))
|
||||
return false;
|
||||
};
|
||||
return true;
|
||||
}
|
||||
|
||||
RandomNumberGenerator &m_rng;
|
||||
const PK_Encryptor &m_encryptor;
|
||||
unsigned int m_ciphertextLength;
|
||||
SecByteBlock m_ciphertext;
|
||||
};
|
||||
|
||||
return new EncryptionFilter(rng, *this, attachment);
|
||||
}
|
||||
|
||||
BufferedTransformation * PK_Decryptor::CreateDecryptionFilter(RandomNumberGenerator &rng, BufferedTransformation *attachment) const
|
||||
{
|
||||
struct DecryptionFilter : public Unflushable<FilterWithInputQueue>
|
||||
{
|
||||
// VC60 complains if this function is missing
|
||||
DecryptionFilter(const DecryptionFilter &x) : Unflushable<FilterWithInputQueue>(NULL), m_rng(x.m_rng), m_decryptor(x.m_decryptor) {}
|
||||
|
||||
DecryptionFilter(RandomNumberGenerator &rng, const PK_Decryptor &decryptor, BufferedTransformation *attachment)
|
||||
: Unflushable<FilterWithInputQueue>(attachment), m_rng(rng), m_decryptor(decryptor)
|
||||
{
|
||||
}
|
||||
|
||||
bool IsolatedMessageEnd(bool blocking)
|
||||
{
|
||||
switch (m_continueAt)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
unsigned int ciphertextLength = m_inQueue.CurrentSize();
|
||||
unsigned int maxPlaintextLength = m_decryptor.MaxPlaintextLength(ciphertextLength);
|
||||
|
||||
SecByteBlock ciphertext(ciphertextLength);
|
||||
m_inQueue.Get(ciphertext, ciphertextLength);
|
||||
m_plaintext.resize(maxPlaintextLength);
|
||||
m_result = m_decryptor.Decrypt(m_rng, ciphertext, ciphertextLength, m_plaintext);
|
||||
if (!m_result.isValidCoding)
|
||||
throw InvalidCiphertext(m_decryptor.AlgorithmName() + ": invalid ciphertext");
|
||||
}
|
||||
|
||||
case 1:
|
||||
if (!Output(1, m_plaintext, m_result.messageLength, 0, blocking))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
RandomNumberGenerator &m_rng;
|
||||
const PK_Decryptor &m_decryptor;
|
||||
SecByteBlock m_plaintext;
|
||||
DecodingResult m_result;
|
||||
};
|
||||
|
||||
return new DecryptionFilter(rng, *this, attachment);
|
||||
}
|
||||
|
||||
unsigned int PK_FixedLengthCryptoSystem::MaxPlaintextLength(unsigned int cipherTextLength) const
|
||||
{
|
||||
if (cipherTextLength == FixedCiphertextLength())
|
||||
return FixedMaxPlaintextLength();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int PK_FixedLengthCryptoSystem::CiphertextLength(unsigned int plainTextLength) const
|
||||
{
|
||||
if (plainTextLength <= FixedMaxPlaintextLength())
|
||||
return FixedCiphertextLength();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
DecodingResult PK_FixedLengthDecryptor::Decrypt(RandomNumberGenerator &rng, const byte *cipherText, unsigned int cipherTextLength, byte *plainText) const
|
||||
{
|
||||
if (cipherTextLength != FixedCiphertextLength())
|
||||
return DecodingResult();
|
||||
|
||||
return FixedLengthDecrypt(rng, cipherText, plainText);
|
||||
}
|
||||
|
||||
unsigned int PK_Signer::Sign(RandomNumberGenerator &rng, PK_MessageAccumulator *messageAccumulator, byte *signature) const
|
||||
{
|
||||
std::auto_ptr<PK_MessageAccumulator> m(messageAccumulator);
|
||||
return SignAndRestart(rng, *m, signature, false);
|
||||
}
|
||||
|
||||
unsigned int PK_Signer::SignMessage(RandomNumberGenerator &rng, const byte *message, unsigned int messageLen, byte *signature) const
|
||||
{
|
||||
std::auto_ptr<PK_MessageAccumulator> m(NewSignatureAccumulator(rng));
|
||||
m->Update(message, messageLen);
|
||||
return SignAndRestart(rng, *m, signature, false);
|
||||
}
|
||||
|
||||
unsigned int PK_Signer::SignMessageWithRecovery(RandomNumberGenerator &rng, const byte *recoverableMessage, unsigned int recoverableMessageLength,
|
||||
const byte *nonrecoverableMessage, unsigned int nonrecoverableMessageLength, byte *signature) const
|
||||
{
|
||||
std::auto_ptr<PK_MessageAccumulator> m(NewSignatureAccumulator(rng));
|
||||
InputRecoverableMessage(*m, recoverableMessage, recoverableMessageLength);
|
||||
m->Update(nonrecoverableMessage, nonrecoverableMessageLength);
|
||||
return SignAndRestart(rng, *m, signature, false);
|
||||
}
|
||||
|
||||
bool PK_Verifier::Verify(PK_MessageAccumulator *messageAccumulator) const
|
||||
{
|
||||
std::auto_ptr<PK_MessageAccumulator> m(messageAccumulator);
|
||||
return VerifyAndRestart(*m);
|
||||
}
|
||||
|
||||
bool PK_Verifier::VerifyMessage(const byte *message, unsigned int messageLen, const byte *signature, unsigned int signatureLength) const
|
||||
{
|
||||
std::auto_ptr<PK_MessageAccumulator> m(NewVerificationAccumulator());
|
||||
InputSignature(*m, signature, signatureLength);
|
||||
m->Update(message, messageLen);
|
||||
return VerifyAndRestart(*m);
|
||||
}
|
||||
|
||||
DecodingResult PK_Verifier::Recover(byte *recoveredMessage, PK_MessageAccumulator *messageAccumulator) const
|
||||
{
|
||||
std::auto_ptr<PK_MessageAccumulator> m(messageAccumulator);
|
||||
return RecoverAndRestart(recoveredMessage, *m);
|
||||
}
|
||||
|
||||
DecodingResult PK_Verifier::RecoverMessage(byte *recoveredMessage,
|
||||
const byte *nonrecoverableMessage, unsigned int nonrecoverableMessageLength,
|
||||
const byte *signature, unsigned int signatureLength) const
|
||||
{
|
||||
std::auto_ptr<PK_MessageAccumulator> m(NewVerificationAccumulator());
|
||||
InputSignature(*m, signature, signatureLength);
|
||||
m->Update(nonrecoverableMessage, nonrecoverableMessageLength);
|
||||
return RecoverAndRestart(recoveredMessage, *m);
|
||||
}
|
||||
|
||||
void SimpleKeyAgreementDomain::GenerateKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const
|
||||
{
|
||||
GeneratePrivateKey(rng, privateKey);
|
||||
GeneratePublicKey(rng, privateKey, publicKey);
|
||||
}
|
||||
|
||||
void AuthenticatedKeyAgreementDomain::GenerateStaticKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const
|
||||
{
|
||||
GenerateStaticPrivateKey(rng, privateKey);
|
||||
GenerateStaticPublicKey(rng, privateKey, publicKey);
|
||||
}
|
||||
|
||||
void AuthenticatedKeyAgreementDomain::GenerateEphemeralKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const
|
||||
{
|
||||
GenerateEphemeralPrivateKey(rng, privateKey);
|
||||
GenerateEphemeralPublicKey(rng, privateKey, publicKey);
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -0,0 +1,746 @@
|
||||
# Microsoft Developer Studio Project File - Name="cryptlib" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 60000
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Static Library" 0x0104
|
||||
|
||||
CFG=cryptlib - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "cryptlib.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "cryptlib.mak" CFG="cryptlib - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "cryptlib - Win32 FIPS 140 Release" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "cryptlib - Win32 FIPS 140 Debug" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "cryptlib - Win32 Release" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "cryptlib - Win32 Debug" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "cryptlib - Win32 FIPS 140 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "cryptlib___Win32_FIPS_140_Release"
|
||||
# PROP BASE Intermediate_Dir "cryptlib___Win32_FIPS_140_Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "FIPS_140_Release"
|
||||
# PROP Intermediate_Dir "FIPS_140_Release"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /G5 /Gz /MT /W3 /GX /Zi /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "USE_PRECOMPILED_HEADERS" /Yu"pch.h" /FD /c
|
||||
# ADD CPP /nologo /G5 /Gz /MT /W3 /GX /Zi /O2 /D "NDEBUG" /D "_WINDOWS" /D "USE_PRECOMPILED_HEADERS" /D "WIN32" /D CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2=1 /Yu"pch.h" /Fd"FIPS_140_Release/cryptopp" /FD /c
|
||||
# ADD BASE RSC /l 0x409
|
||||
# ADD RSC /l 0x409
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo /out:"FIPS_140_Release\cryptopp.lib"
|
||||
|
||||
!ELSEIF "$(CFG)" == "cryptlib - Win32 FIPS 140 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "cryptlib___Win32_FIPS_140_Debug"
|
||||
# PROP BASE Intermediate_Dir "cryptlib___Win32_FIPS_140_Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "FIPS_140_Debug"
|
||||
# PROP Intermediate_Dir "FIPS_140_Debug"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MTd /W3 /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "USE_PRECOMPILED_HEADERS" /Yu"pch.h" /FD /c
|
||||
# ADD CPP /nologo /G5 /Gz /MTd /W3 /GX /ZI /Od /D "_DEBUG" /D "_WINDOWS" /D "USE_PRECOMPILED_HEADERS" /D "WIN32" /D CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2=1 /Yu"pch.h" /Fd"FIPS_140_Debug/cryptopp" /FD /c
|
||||
# ADD BASE RSC /l 0x409
|
||||
# ADD RSC /l 0x409
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo /out:"FIPS_140_Debug\cryptopp.lib"
|
||||
|
||||
!ELSEIF "$(CFG)" == "cryptlib - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "cryptlib"
|
||||
# PROP BASE Intermediate_Dir "cryptlib"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /Zi /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "USE_PRECOMPILED_HEADERS" /YX"pch.h" /FD /c
|
||||
# ADD BASE RSC /l 0x409
|
||||
# ADD RSC /l 0x409
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
|
||||
!ELSEIF "$(CFG)" == "cryptlib - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "cryptli0"
|
||||
# PROP BASE Intermediate_Dir "cryptli0"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /Z7 /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
|
||||
# ADD CPP /nologo /MDd /W3 /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "USE_PRECOMPILED_HEADERS" /YX"pch.h" /FD /c
|
||||
# ADD BASE RSC /l 0x409
|
||||
# ADD RSC /l 0x409
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "cryptlib - Win32 FIPS 140 Release"
|
||||
# Name "cryptlib - Win32 FIPS 140 Debug"
|
||||
# Name "cryptlib - Win32 Release"
|
||||
# Name "cryptlib - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter ".cpp"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\algebra.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\algparam.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\asn.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\basecode.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\channels.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cryptlib.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\des.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\dessp.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\eprecomp.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\files.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\filters.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\fips140.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\hex.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\integer.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\iterhash.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\md5.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\misc.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\modes.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\mqueue.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\nbtheory.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\oaep.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\osrng.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\pkcspad.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\polynomi.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\pssr.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\pubkey.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\queue.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\randpool.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\rsa.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\sha.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\strciphr.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter ".;.h"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\3way.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\adler32.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\aes.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\algebra.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\algparam.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\arc4.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\argnames.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\asn.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\base64.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\basecode.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\blowfish.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\blumshub.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cast.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cbcmac.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\channels.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\config.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\crc.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\cryptlib.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\default.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\des.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\dh.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\dh2.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\diamond.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\dmac.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\dsa.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ec2n.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\eccrypto.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ecp.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\elgamal.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\eprecomp.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\esign.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\files.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\filters.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\fips140.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\fltrimpl.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gf256.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gf2_32.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gf2n.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gfpcrypt.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gost.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\gzip.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\haval.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\hex.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\hmac.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\hrtimer.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ida.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\idea.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\integer.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\iterhash.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\lubyrack.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\luc.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\mars.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\md2.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\md4.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\md5.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\md5mac.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\mdc.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\misc.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\modarith.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\modes.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\modexppc.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\mqueue.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\mqv.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\nbtheory.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\network.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\nr.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\oaep.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\oids.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\osrng.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\panama.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\pch.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\pkcspad.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\polynomi.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\pssr.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\pubkey.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\pwdbased.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\queue.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\rabin.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\randpool.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\rc2.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\rc5.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\rc6.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\rijndael.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\ripemd.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\rng.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\rsa.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\rw.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\safer.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\seal.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\secblock.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\seckey.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\serpent.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\sha.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\shark.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\simple.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\skipjack.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\smartptr.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\socketft.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\square.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\strciphr.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\tea.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\tiger.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\trdlocal.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\trunhash.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\twofish.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\wait.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\wake.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\winpipes.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\words.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\xormac.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\xtr.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\xtrcrypt.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\zdeflate.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\zinflate.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\zlib.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Miscellaneous"
|
||||
|
||||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\Doxyfile
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\GNUmakefile
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\license.txt
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\readme.txt
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,104 @@
|
||||
#ifndef CRYPTOPP_DEFAULT_H
|
||||
#define CRYPTOPP_DEFAULT_H
|
||||
|
||||
#include "sha.h"
|
||||
#include "hmac.h"
|
||||
#include "des.h"
|
||||
#include "filters.h"
|
||||
#include "modes.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
typedef DES_EDE2 Default_BlockCipher;
|
||||
typedef SHA DefaultHashModule;
|
||||
typedef HMAC<DefaultHashModule> DefaultMAC;
|
||||
|
||||
//! Password-Based Encryptor using DES-EDE2
|
||||
class DefaultEncryptor : public ProxyFilter
|
||||
{
|
||||
public:
|
||||
DefaultEncryptor(const char *passphrase, BufferedTransformation *attachment = NULL);
|
||||
DefaultEncryptor(const byte *passphrase, unsigned int passphraseLength, BufferedTransformation *attachment = NULL);
|
||||
|
||||
protected:
|
||||
void FirstPut(const byte *);
|
||||
void LastPut(const byte *inString, unsigned int length);
|
||||
|
||||
private:
|
||||
SecByteBlock m_passphrase;
|
||||
CBC_Mode<Default_BlockCipher>::Encryption m_cipher;
|
||||
};
|
||||
|
||||
//! Password-Based Decryptor using DES-EDE2
|
||||
class DefaultDecryptor : public ProxyFilter
|
||||
{
|
||||
public:
|
||||
DefaultDecryptor(const char *passphrase, BufferedTransformation *attachment = NULL, bool throwException=true);
|
||||
DefaultDecryptor(const byte *passphrase, unsigned int passphraseLength, BufferedTransformation *attachment = NULL, bool throwException=true);
|
||||
|
||||
class Err : public Exception
|
||||
{
|
||||
public:
|
||||
Err(const std::string &s)
|
||||
: Exception(DATA_INTEGRITY_CHECK_FAILED, s) {}
|
||||
};
|
||||
class KeyBadErr : public Err {public: KeyBadErr() : Err("DefaultDecryptor: cannot decrypt message with this passphrase") {}};
|
||||
|
||||
enum State {WAITING_FOR_KEYCHECK, KEY_GOOD, KEY_BAD};
|
||||
State CurrentState() const {return m_state;}
|
||||
|
||||
protected:
|
||||
void FirstPut(const byte *inString);
|
||||
void LastPut(const byte *inString, unsigned int length);
|
||||
|
||||
State m_state;
|
||||
|
||||
private:
|
||||
void CheckKey(const byte *salt, const byte *keyCheck);
|
||||
|
||||
SecByteBlock m_passphrase;
|
||||
CBC_Mode<Default_BlockCipher>::Decryption m_cipher;
|
||||
member_ptr<FilterWithBufferedInput> m_decryptor;
|
||||
bool m_throwException;
|
||||
};
|
||||
|
||||
//! Password-Based Encryptor using DES-EDE2 and HMAC/SHA-1
|
||||
class DefaultEncryptorWithMAC : public ProxyFilter
|
||||
{
|
||||
public:
|
||||
DefaultEncryptorWithMAC(const char *passphrase, BufferedTransformation *attachment = NULL);
|
||||
DefaultEncryptorWithMAC(const byte *passphrase, unsigned int passphraseLength, BufferedTransformation *attachment = NULL);
|
||||
|
||||
protected:
|
||||
void FirstPut(const byte *inString) {}
|
||||
void LastPut(const byte *inString, unsigned int length);
|
||||
|
||||
private:
|
||||
member_ptr<DefaultMAC> m_mac;
|
||||
};
|
||||
|
||||
//! Password-Based Decryptor using DES-EDE2 and HMAC/SHA-1
|
||||
class DefaultDecryptorWithMAC : public ProxyFilter
|
||||
{
|
||||
public:
|
||||
class MACBadErr : public DefaultDecryptor::Err {public: MACBadErr() : DefaultDecryptor::Err("DefaultDecryptorWithMAC: MAC check failed") {}};
|
||||
|
||||
DefaultDecryptorWithMAC(const char *passphrase, BufferedTransformation *attachment = NULL, bool throwException=true);
|
||||
DefaultDecryptorWithMAC(const byte *passphrase, unsigned int passphraseLength, BufferedTransformation *attachment = NULL, bool throwException=true);
|
||||
|
||||
DefaultDecryptor::State CurrentState() const;
|
||||
bool CheckLastMAC() const;
|
||||
|
||||
protected:
|
||||
void FirstPut(const byte *inString) {}
|
||||
void LastPut(const byte *inString, unsigned int length);
|
||||
|
||||
private:
|
||||
member_ptr<DefaultMAC> m_mac;
|
||||
HashVerifier *m_hashVerifier;
|
||||
bool m_throwException;
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,464 @@
|
||||
// des.cpp - modified by Wei Dai from Phil Karn's des.c
|
||||
// The original code and all modifications are in the public domain.
|
||||
|
||||
/*
|
||||
* This is a major rewrite of my old public domain DES code written
|
||||
* circa 1987, which in turn borrowed heavily from Jim Gillogly's 1977
|
||||
* public domain code. I pretty much kept my key scheduling code, but
|
||||
* the actual encrypt/decrypt routines are taken from from Richard
|
||||
* Outerbridge's DES code as printed in Schneier's "Applied Cryptography."
|
||||
*
|
||||
* This code is in the public domain. I would appreciate bug reports and
|
||||
* enhancements.
|
||||
*
|
||||
* Phil Karn KA9Q, [email protected], August 1994.
|
||||
*/
|
||||
|
||||
#include "pch.h"
|
||||
#include "misc.h"
|
||||
#include "des.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
static inline bool CheckParity(byte b)
|
||||
{
|
||||
unsigned int a = b ^ (b >> 4);
|
||||
return ((a ^ (a>>1) ^ (a>>2) ^ (a>>3)) & 1) == 1;
|
||||
}
|
||||
|
||||
bool DES::CheckKeyParityBits(const byte *key)
|
||||
{
|
||||
for (unsigned int i=0; i<8; i++)
|
||||
if (!CheckParity(key[i]))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void DES::CorrectKeyParityBits(byte *key)
|
||||
{
|
||||
for (unsigned int i=0; i<8; i++)
|
||||
if (!CheckParity(key[i]))
|
||||
key[i] ^= 1;
|
||||
}
|
||||
|
||||
/* Tables defined in the Data Encryption Standard documents
|
||||
* Three of these tables, the initial permutation, the final
|
||||
* permutation and the expansion operator, are regular enough that
|
||||
* for speed, we hard-code them. They're here for reference only.
|
||||
* Also, the S and P boxes are used by a separate program, gensp.c,
|
||||
* to build the combined SP box, Spbox[]. They're also here just
|
||||
* for reference.
|
||||
*/
|
||||
#ifdef notdef
|
||||
/* initial permutation IP */
|
||||
static byte ip[] = {
|
||||
58, 50, 42, 34, 26, 18, 10, 2,
|
||||
60, 52, 44, 36, 28, 20, 12, 4,
|
||||
62, 54, 46, 38, 30, 22, 14, 6,
|
||||
64, 56, 48, 40, 32, 24, 16, 8,
|
||||
57, 49, 41, 33, 25, 17, 9, 1,
|
||||
59, 51, 43, 35, 27, 19, 11, 3,
|
||||
61, 53, 45, 37, 29, 21, 13, 5,
|
||||
63, 55, 47, 39, 31, 23, 15, 7
|
||||
};
|
||||
|
||||
/* final permutation IP^-1 */
|
||||
static byte fp[] = {
|
||||
40, 8, 48, 16, 56, 24, 64, 32,
|
||||
39, 7, 47, 15, 55, 23, 63, 31,
|
||||
38, 6, 46, 14, 54, 22, 62, 30,
|
||||
37, 5, 45, 13, 53, 21, 61, 29,
|
||||
36, 4, 44, 12, 52, 20, 60, 28,
|
||||
35, 3, 43, 11, 51, 19, 59, 27,
|
||||
34, 2, 42, 10, 50, 18, 58, 26,
|
||||
33, 1, 41, 9, 49, 17, 57, 25
|
||||
};
|
||||
/* expansion operation matrix */
|
||||
static byte ei[] = {
|
||||
32, 1, 2, 3, 4, 5,
|
||||
4, 5, 6, 7, 8, 9,
|
||||
8, 9, 10, 11, 12, 13,
|
||||
12, 13, 14, 15, 16, 17,
|
||||
16, 17, 18, 19, 20, 21,
|
||||
20, 21, 22, 23, 24, 25,
|
||||
24, 25, 26, 27, 28, 29,
|
||||
28, 29, 30, 31, 32, 1
|
||||
};
|
||||
/* The (in)famous S-boxes */
|
||||
static byte sbox[8][64] = {
|
||||
/* S1 */
|
||||
14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
|
||||
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
|
||||
4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
|
||||
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13,
|
||||
|
||||
/* S2 */
|
||||
15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
|
||||
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
|
||||
0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
|
||||
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9,
|
||||
|
||||
/* S3 */
|
||||
10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
|
||||
13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
|
||||
13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
|
||||
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12,
|
||||
|
||||
/* S4 */
|
||||
7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
|
||||
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
|
||||
10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
|
||||
3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14,
|
||||
|
||||
/* S5 */
|
||||
2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
|
||||
14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
|
||||
4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
|
||||
11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3,
|
||||
|
||||
/* S6 */
|
||||
12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
|
||||
10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
|
||||
9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
|
||||
4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13,
|
||||
|
||||
/* S7 */
|
||||
4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
|
||||
13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
|
||||
1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
|
||||
6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12,
|
||||
|
||||
/* S8 */
|
||||
13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
|
||||
1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
|
||||
7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
|
||||
2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
|
||||
};
|
||||
|
||||
/* 32-bit permutation function P used on the output of the S-boxes */
|
||||
static byte p32i[] = {
|
||||
16, 7, 20, 21,
|
||||
29, 12, 28, 17,
|
||||
1, 15, 23, 26,
|
||||
5, 18, 31, 10,
|
||||
2, 8, 24, 14,
|
||||
32, 27, 3, 9,
|
||||
19, 13, 30, 6,
|
||||
22, 11, 4, 25
|
||||
};
|
||||
#endif
|
||||
|
||||
/* permuted choice table (key) */
|
||||
static const byte pc1[] = {
|
||||
57, 49, 41, 33, 25, 17, 9,
|
||||
1, 58, 50, 42, 34, 26, 18,
|
||||
10, 2, 59, 51, 43, 35, 27,
|
||||
19, 11, 3, 60, 52, 44, 36,
|
||||
|
||||
63, 55, 47, 39, 31, 23, 15,
|
||||
7, 62, 54, 46, 38, 30, 22,
|
||||
14, 6, 61, 53, 45, 37, 29,
|
||||
21, 13, 5, 28, 20, 12, 4
|
||||
};
|
||||
|
||||
/* number left rotations of pc1 */
|
||||
static const byte totrot[] = {
|
||||
1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28
|
||||
};
|
||||
|
||||
/* permuted choice key (table) */
|
||||
static const byte pc2[] = {
|
||||
14, 17, 11, 24, 1, 5,
|
||||
3, 28, 15, 6, 21, 10,
|
||||
23, 19, 12, 4, 26, 8,
|
||||
16, 7, 27, 20, 13, 2,
|
||||
41, 52, 31, 37, 47, 55,
|
||||
30, 40, 51, 45, 33, 48,
|
||||
44, 49, 39, 56, 34, 53,
|
||||
46, 42, 50, 36, 29, 32
|
||||
};
|
||||
|
||||
/* End of DES-defined tables */
|
||||
|
||||
/* bit 0 is left-most in byte */
|
||||
static const int bytebit[] = {
|
||||
0200,0100,040,020,010,04,02,01
|
||||
};
|
||||
|
||||
/* Set key (initialize key schedule array) */
|
||||
void DES::Base::UncheckedSetKey(CipherDir dir, const byte *key, unsigned int length)
|
||||
{
|
||||
AssertValidKeyLength(length);
|
||||
|
||||
SecByteBlock buffer(56+56+8);
|
||||
byte *const pc1m=buffer; /* place to modify pc1 into */
|
||||
byte *const pcr=pc1m+56; /* place to rotate pc1 into */
|
||||
byte *const ks=pcr+56;
|
||||
register int i,j,l;
|
||||
int m;
|
||||
|
||||
for (j=0; j<56; j++) { /* convert pc1 to bits of key */
|
||||
l=pc1[j]-1; /* integer bit location */
|
||||
m = l & 07; /* find bit */
|
||||
pc1m[j]=(key[l>>3] & /* find which key byte l is in */
|
||||
bytebit[m]) /* and which bit of that byte */
|
||||
? 1 : 0; /* and store 1-bit result */
|
||||
}
|
||||
for (i=0; i<16; i++) { /* key chunk for each iteration */
|
||||
memset(ks,0,8); /* Clear key schedule */
|
||||
for (j=0; j<56; j++) /* rotate pc1 the right amount */
|
||||
pcr[j] = pc1m[(l=j+totrot[i])<(j<28? 28 : 56) ? l: l-28];
|
||||
/* rotate left and right halves independently */
|
||||
for (j=0; j<48; j++){ /* select bits individually */
|
||||
/* check bit that goes to ks[j] */
|
||||
if (pcr[pc2[j]-1]){
|
||||
/* mask it in if it's there */
|
||||
l= j % 6;
|
||||
ks[j/6] |= bytebit[l] >> 2;
|
||||
}
|
||||
}
|
||||
/* Now convert to odd/even interleaved form for use in F */
|
||||
k[2*i] = ((word32)ks[0] << 24)
|
||||
| ((word32)ks[2] << 16)
|
||||
| ((word32)ks[4] << 8)
|
||||
| ((word32)ks[6]);
|
||||
k[2*i+1] = ((word32)ks[1] << 24)
|
||||
| ((word32)ks[3] << 16)
|
||||
| ((word32)ks[5] << 8)
|
||||
| ((word32)ks[7]);
|
||||
}
|
||||
|
||||
if (dir==DECRYPTION) // reverse key schedule order
|
||||
for (i=0; i<16; i+=2)
|
||||
{
|
||||
std::swap(k[i], k[32-2-i]);
|
||||
std::swap(k[i+1], k[32-1-i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Richard Outerbridge's initial permutation algorithm
|
||||
/*
|
||||
inline void IPERM(word32 &left, word32 &right)
|
||||
{
|
||||
word32 work;
|
||||
|
||||
work = ((left >> 4) ^ right) & 0x0f0f0f0f;
|
||||
right ^= work;
|
||||
left ^= work << 4;
|
||||
work = ((left >> 16) ^ right) & 0xffff;
|
||||
right ^= work;
|
||||
left ^= work << 16;
|
||||
work = ((right >> 2) ^ left) & 0x33333333;
|
||||
left ^= work;
|
||||
right ^= (work << 2);
|
||||
work = ((right >> 8) ^ left) & 0xff00ff;
|
||||
left ^= work;
|
||||
right ^= (work << 8);
|
||||
right = rotl(right, 1);
|
||||
work = (left ^ right) & 0xaaaaaaaa;
|
||||
left ^= work;
|
||||
right ^= work;
|
||||
left = rotl(left, 1);
|
||||
}
|
||||
inline void FPERM(word32 &left, word32 &right)
|
||||
{
|
||||
word32 work;
|
||||
|
||||
right = rotr(right, 1);
|
||||
work = (left ^ right) & 0xaaaaaaaa;
|
||||
left ^= work;
|
||||
right ^= work;
|
||||
left = rotr(left, 1);
|
||||
work = ((left >> 8) ^ right) & 0xff00ff;
|
||||
right ^= work;
|
||||
left ^= work << 8;
|
||||
work = ((left >> 2) ^ right) & 0x33333333;
|
||||
right ^= work;
|
||||
left ^= work << 2;
|
||||
work = ((right >> 16) ^ left) & 0xffff;
|
||||
left ^= work;
|
||||
right ^= work << 16;
|
||||
work = ((right >> 4) ^ left) & 0x0f0f0f0f;
|
||||
left ^= work;
|
||||
right ^= work << 4;
|
||||
}
|
||||
*/
|
||||
|
||||
// Wei Dai's modification to Richard Outerbridge's initial permutation
|
||||
// algorithm, this one is faster if you have access to rotate instructions
|
||||
// (like in MSVC)
|
||||
static inline void IPERM(word32 &left, word32 &right)
|
||||
{
|
||||
word32 work;
|
||||
|
||||
right = rotlFixed(right, 4U);
|
||||
work = (left ^ right) & 0xf0f0f0f0;
|
||||
left ^= work;
|
||||
right = rotrFixed(right^work, 20U);
|
||||
work = (left ^ right) & 0xffff0000;
|
||||
left ^= work;
|
||||
right = rotrFixed(right^work, 18U);
|
||||
work = (left ^ right) & 0x33333333;
|
||||
left ^= work;
|
||||
right = rotrFixed(right^work, 6U);
|
||||
work = (left ^ right) & 0x00ff00ff;
|
||||
left ^= work;
|
||||
right = rotlFixed(right^work, 9U);
|
||||
work = (left ^ right) & 0xaaaaaaaa;
|
||||
left = rotlFixed(left^work, 1U);
|
||||
right ^= work;
|
||||
}
|
||||
|
||||
static inline void FPERM(word32 &left, word32 &right)
|
||||
{
|
||||
word32 work;
|
||||
|
||||
right = rotrFixed(right, 1U);
|
||||
work = (left ^ right) & 0xaaaaaaaa;
|
||||
right ^= work;
|
||||
left = rotrFixed(left^work, 9U);
|
||||
work = (left ^ right) & 0x00ff00ff;
|
||||
right ^= work;
|
||||
left = rotlFixed(left^work, 6U);
|
||||
work = (left ^ right) & 0x33333333;
|
||||
right ^= work;
|
||||
left = rotlFixed(left^work, 18U);
|
||||
work = (left ^ right) & 0xffff0000;
|
||||
right ^= work;
|
||||
left = rotlFixed(left^work, 20U);
|
||||
work = (left ^ right) & 0xf0f0f0f0;
|
||||
right ^= work;
|
||||
left = rotrFixed(left^work, 4U);
|
||||
}
|
||||
|
||||
void DES::Base::RawProcessBlock(word32 &l_, word32 &r_) const
|
||||
{
|
||||
word32 l = l_, r = r_;
|
||||
const word32 *kptr=k;
|
||||
|
||||
for (unsigned i=0; i<8; i++)
|
||||
{
|
||||
word32 work = rotrFixed(r, 4U) ^ kptr[4*i+0];
|
||||
l ^= Spbox[6][(work) & 0x3f]
|
||||
^ Spbox[4][(work >> 8) & 0x3f]
|
||||
^ Spbox[2][(work >> 16) & 0x3f]
|
||||
^ Spbox[0][(work >> 24) & 0x3f];
|
||||
work = r ^ kptr[4*i+1];
|
||||
l ^= Spbox[7][(work) & 0x3f]
|
||||
^ Spbox[5][(work >> 8) & 0x3f]
|
||||
^ Spbox[3][(work >> 16) & 0x3f]
|
||||
^ Spbox[1][(work >> 24) & 0x3f];
|
||||
|
||||
work = rotrFixed(l, 4U) ^ kptr[4*i+2];
|
||||
r ^= Spbox[6][(work) & 0x3f]
|
||||
^ Spbox[4][(work >> 8) & 0x3f]
|
||||
^ Spbox[2][(work >> 16) & 0x3f]
|
||||
^ Spbox[0][(work >> 24) & 0x3f];
|
||||
work = l ^ kptr[4*i+3];
|
||||
r ^= Spbox[7][(work) & 0x3f]
|
||||
^ Spbox[5][(work >> 8) & 0x3f]
|
||||
^ Spbox[3][(work >> 16) & 0x3f]
|
||||
^ Spbox[1][(work >> 24) & 0x3f];
|
||||
}
|
||||
|
||||
l_ = l; r_ = r;
|
||||
}
|
||||
|
||||
typedef BlockGetAndPut<word32, BigEndian> Block;
|
||||
|
||||
// Encrypt or decrypt a block of data in ECB mode
|
||||
void DES::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
|
||||
{
|
||||
word32 l,r;
|
||||
Block::Get(inBlock)(l)(r);
|
||||
IPERM(l,r);
|
||||
|
||||
const word32 *kptr=k;
|
||||
|
||||
for (unsigned i=0; i<8; i++)
|
||||
{
|
||||
word32 work = rotrFixed(r, 4U) ^ kptr[4*i+0];
|
||||
l ^= Spbox[6][(work) & 0x3f]
|
||||
^ Spbox[4][(work >> 8) & 0x3f]
|
||||
^ Spbox[2][(work >> 16) & 0x3f]
|
||||
^ Spbox[0][(work >> 24) & 0x3f];
|
||||
work = r ^ kptr[4*i+1];
|
||||
l ^= Spbox[7][(work) & 0x3f]
|
||||
^ Spbox[5][(work >> 8) & 0x3f]
|
||||
^ Spbox[3][(work >> 16) & 0x3f]
|
||||
^ Spbox[1][(work >> 24) & 0x3f];
|
||||
|
||||
work = rotrFixed(l, 4U) ^ kptr[4*i+2];
|
||||
r ^= Spbox[6][(work) & 0x3f]
|
||||
^ Spbox[4][(work >> 8) & 0x3f]
|
||||
^ Spbox[2][(work >> 16) & 0x3f]
|
||||
^ Spbox[0][(work >> 24) & 0x3f];
|
||||
work = l ^ kptr[4*i+3];
|
||||
r ^= Spbox[7][(work) & 0x3f]
|
||||
^ Spbox[5][(work >> 8) & 0x3f]
|
||||
^ Spbox[3][(work >> 16) & 0x3f]
|
||||
^ Spbox[1][(work >> 24) & 0x3f];
|
||||
}
|
||||
|
||||
FPERM(l,r);
|
||||
Block::Put(xorBlock, outBlock)(r)(l);
|
||||
}
|
||||
|
||||
void DES_EDE2::Base::UncheckedSetKey(CipherDir dir, const byte *key, unsigned int length)
|
||||
{
|
||||
AssertValidKeyLength(length);
|
||||
|
||||
m_des1.UncheckedSetKey(dir, key);
|
||||
m_des2.UncheckedSetKey(ReverseCipherDir(dir), key+8);
|
||||
}
|
||||
|
||||
void DES_EDE2::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
|
||||
{
|
||||
word32 l,r;
|
||||
Block::Get(inBlock)(l)(r);
|
||||
IPERM(l,r);
|
||||
m_des1.RawProcessBlock(l, r);
|
||||
m_des2.RawProcessBlock(r, l);
|
||||
m_des1.RawProcessBlock(l, r);
|
||||
FPERM(l,r);
|
||||
Block::Put(xorBlock, outBlock)(r)(l);
|
||||
}
|
||||
|
||||
void DES_EDE3::Base::UncheckedSetKey(CipherDir dir, const byte *key, unsigned int length)
|
||||
{
|
||||
AssertValidKeyLength(length);
|
||||
|
||||
m_des1.UncheckedSetKey(dir, key+(dir==ENCRYPTION?0:2*8));
|
||||
m_des2.UncheckedSetKey(ReverseCipherDir(dir), key+8);
|
||||
m_des3.UncheckedSetKey(dir, key+(dir==DECRYPTION?0:2*8));
|
||||
}
|
||||
|
||||
void DES_EDE3::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
|
||||
{
|
||||
word32 l,r;
|
||||
Block::Get(inBlock)(l)(r);
|
||||
IPERM(l,r);
|
||||
m_des1.RawProcessBlock(l, r);
|
||||
m_des2.RawProcessBlock(r, l);
|
||||
m_des3.RawProcessBlock(l, r);
|
||||
FPERM(l,r);
|
||||
Block::Put(xorBlock, outBlock)(r)(l);
|
||||
}
|
||||
|
||||
void DES_XEX3::Base::UncheckedSetKey(CipherDir dir, const byte *key, unsigned int length)
|
||||
{
|
||||
AssertValidKeyLength(length);
|
||||
|
||||
memcpy(m_x1, key+(dir==ENCRYPTION?0:2*8), BLOCKSIZE);
|
||||
m_des.UncheckedSetKey(dir, key+8);
|
||||
memcpy(m_x3, key+(dir==DECRYPTION?0:2*8), BLOCKSIZE);
|
||||
}
|
||||
|
||||
void DES_XEX3::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
|
||||
{
|
||||
xorbuf(outBlock, inBlock, m_x1, BLOCKSIZE);
|
||||
m_des.ProcessAndXorBlock(outBlock, xorBlock, outBlock);
|
||||
xorbuf(outBlock, m_x3, BLOCKSIZE);
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -0,0 +1,133 @@
|
||||
#ifndef CRYPTOPP_DES_H
|
||||
#define CRYPTOPP_DES_H
|
||||
|
||||
/** \file
|
||||
*/
|
||||
|
||||
#include "seckey.h"
|
||||
#include "secblock.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
struct DES_Info : public FixedBlockSize<8>, public FixedKeyLength<8>
|
||||
{
|
||||
static const char *StaticAlgorithmName() {return "DES";}
|
||||
};
|
||||
|
||||
/// <a href="http://www.weidai.com/scan-mirror/cs.html#DES">DES</a>
|
||||
/*! The DES implementation in Crypto++ ignores the parity bits
|
||||
(the least significant bits of each byte) in the key. However
|
||||
you can use CheckKeyParityBits() and CorrectKeyParityBits() to
|
||||
check or correct the parity bits if you wish. */
|
||||
class DES : public DES_Info, public BlockCipherDocumentation
|
||||
{
|
||||
class Base : public BlockCipherBaseTemplate<DES_Info>
|
||||
{
|
||||
public:
|
||||
void UncheckedSetKey(CipherDir direction, const byte *userKey, unsigned int length = 8);
|
||||
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
|
||||
|
||||
// exposed for faster Triple-DES
|
||||
void RawProcessBlock(word32 &l, word32 &r) const;
|
||||
|
||||
protected:
|
||||
static const word32 Spbox[8][64];
|
||||
|
||||
FixedSizeSecBlock<word32, 32> k;
|
||||
};
|
||||
|
||||
public:
|
||||
//! check DES key parity bits
|
||||
static bool CheckKeyParityBits(const byte *key);
|
||||
//! correct DES key parity bits
|
||||
static void CorrectKeyParityBits(byte *key);
|
||||
|
||||
typedef BlockCipherTemplate<ENCRYPTION, Base> Encryption;
|
||||
typedef BlockCipherTemplate<DECRYPTION, Base> Decryption;
|
||||
};
|
||||
|
||||
struct DES_EDE2_Info : public FixedBlockSize<8>, public FixedKeyLength<16>
|
||||
{
|
||||
static const char *StaticAlgorithmName() {return "DES-EDE2";}
|
||||
};
|
||||
|
||||
/// <a href="http://www.weidai.com/scan-mirror/cs.html#DESede">DES-EDE2</a>
|
||||
class DES_EDE2 : public DES_EDE2_Info, public BlockCipherDocumentation
|
||||
{
|
||||
class Base : public BlockCipherBaseTemplate<DES_EDE2_Info>
|
||||
{
|
||||
public:
|
||||
void UncheckedSetKey(CipherDir direction, const byte *userKey, unsigned int length);
|
||||
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
|
||||
|
||||
protected:
|
||||
DES::Encryption m_des1, m_des2;
|
||||
};
|
||||
|
||||
public:
|
||||
typedef BlockCipherTemplate<ENCRYPTION, Base> Encryption;
|
||||
typedef BlockCipherTemplate<DECRYPTION, Base> Decryption;
|
||||
};
|
||||
|
||||
struct DES_EDE3_Info : public FixedBlockSize<8>, public FixedKeyLength<24>
|
||||
{
|
||||
static const char *StaticAlgorithmName() {return "DES-EDE3";}
|
||||
};
|
||||
|
||||
/// <a href="http://www.weidai.com/scan-mirror/cs.html#DESede">DES-EDE3</a>
|
||||
class DES_EDE3 : public DES_EDE3_Info, public BlockCipherDocumentation
|
||||
{
|
||||
class Base : public BlockCipherBaseTemplate<DES_EDE3_Info>
|
||||
{
|
||||
public:
|
||||
void UncheckedSetKey(CipherDir dir, const byte *key, unsigned int length);
|
||||
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
|
||||
|
||||
protected:
|
||||
DES::Encryption m_des1, m_des2, m_des3;
|
||||
};
|
||||
|
||||
public:
|
||||
typedef BlockCipherTemplate<ENCRYPTION, Base> Encryption;
|
||||
typedef BlockCipherTemplate<DECRYPTION, Base> Decryption;
|
||||
};
|
||||
|
||||
struct DES_XEX3_Info : public FixedBlockSize<8>, public FixedKeyLength<24>
|
||||
{
|
||||
static const char *StaticAlgorithmName() {return "DES-XEX3";}
|
||||
};
|
||||
|
||||
/// <a href="http://www.weidai.com/scan-mirror/cs.html#DESX">DES-XEX3</a>, AKA DESX
|
||||
class DES_XEX3 : public DES_XEX3_Info, public BlockCipherDocumentation
|
||||
{
|
||||
class Base : public BlockCipherBaseTemplate<DES_XEX3_Info>
|
||||
{
|
||||
public:
|
||||
void UncheckedSetKey(CipherDir dir, const byte *key, unsigned int length);
|
||||
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const;
|
||||
|
||||
protected:
|
||||
FixedSizeSecBlock<byte, BLOCKSIZE> m_x1, m_x3;
|
||||
DES::Encryption m_des;
|
||||
};
|
||||
|
||||
public:
|
||||
typedef BlockCipherTemplate<ENCRYPTION, Base> Encryption;
|
||||
typedef BlockCipherTemplate<DECRYPTION, Base> Decryption;
|
||||
};
|
||||
|
||||
typedef DES::Encryption DESEncryption;
|
||||
typedef DES::Decryption DESDecryption;
|
||||
|
||||
typedef DES_EDE2::Encryption DES_EDE2_Encryption;
|
||||
typedef DES_EDE2::Decryption DES_EDE2_Decryption;
|
||||
|
||||
typedef DES_EDE3::Encryption DES_EDE3_Encryption;
|
||||
typedef DES_EDE3::Decryption DES_EDE3_Decryption;
|
||||
|
||||
typedef DES_XEX3::Encryption DES_XEX3_Encryption;
|
||||
typedef DES_XEX3::Decryption DES_XEX3_Decryption;
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,171 @@
|
||||
0101010101010101 95F8A5E5DD31D900 8000000000000000
|
||||
0101010101010101 DD7F121CA5015619 4000000000000000
|
||||
0101010101010101 2E8653104F3834EA 2000000000000000
|
||||
0101010101010101 4BD388FF6CD81D4F 1000000000000000
|
||||
0101010101010101 20B9E767B2FB1456 0800000000000000
|
||||
0101010101010101 55579380D77138EF 0400000000000000
|
||||
0101010101010101 6CC5DEFAAF04512F 0200000000000000
|
||||
0101010101010101 0D9F279BA5D87260 0100000000000000
|
||||
0101010101010101 D9031B0271BD5A0A 0080000000000000
|
||||
0101010101010101 424250B37C3DD951 0040000000000000
|
||||
0101010101010101 B8061B7ECD9A21E5 0020000000000000
|
||||
0101010101010101 F15D0F286B65BD28 0010000000000000
|
||||
0101010101010101 ADD0CC8D6E5DEBA1 0008000000000000
|
||||
0101010101010101 E6D5F82752AD63D1 0004000000000000
|
||||
0101010101010101 ECBFE3BD3F591A5E 0002000000000000
|
||||
0101010101010101 F356834379D165CD 0001000000000000
|
||||
0101010101010101 2B9F982F20037FA9 0000800000000000
|
||||
0101010101010101 889DE068A16F0BE6 0000400000000000
|
||||
0101010101010101 E19E275D846A1298 0000200000000000
|
||||
0101010101010101 329A8ED523D71AEC 0000100000000000
|
||||
0101010101010101 E7FCE22557D23C97 0000080000000000
|
||||
0101010101010101 12A9F5817FF2D65D 0000040000000000
|
||||
0101010101010101 A484C3AD38DC9C19 0000020000000000
|
||||
0101010101010101 FBE00A8A1EF8AD72 0000010000000000
|
||||
0101010101010101 750D079407521363 0000008000000000
|
||||
0101010101010101 64FEED9C724C2FAF 0000004000000000
|
||||
0101010101010101 F02B263B328E2B60 0000002000000000
|
||||
0101010101010101 9D64555A9A10B852 0000001000000000
|
||||
0101010101010101 D106FF0BED5255D7 0000000800000000
|
||||
0101010101010101 E1652C6B138C64A5 0000000400000000
|
||||
0101010101010101 E428581186EC8F46 0000000200000000
|
||||
0101010101010101 AEB5F5EDE22D1A36 0000000100000000
|
||||
0101010101010101 E943D7568AEC0C5C 0000000080000000
|
||||
0101010101010101 DF98C8276F54B04B 0000000040000000
|
||||
0101010101010101 B160E4680F6C696F 0000000020000000
|
||||
0101010101010101 FA0752B07D9C4AB8 0000000010000000
|
||||
0101010101010101 CA3A2B036DBC8502 0000000008000000
|
||||
0101010101010101 5E0905517BB59BCF 0000000004000000
|
||||
0101010101010101 814EEB3B91D90726 0000000002000000
|
||||
0101010101010101 4D49DB1532919C9F 0000000001000000
|
||||
0101010101010101 25EB5FC3F8CF0621 0000000000800000
|
||||
0101010101010101 AB6A20C0620D1C6F 0000000000400000
|
||||
0101010101010101 79E90DBC98F92CCA 0000000000200000
|
||||
0101010101010101 866ECEDD8072BB0E 0000000000100000
|
||||
0101010101010101 8B54536F2F3E64A8 0000000000080000
|
||||
0101010101010101 EA51D3975595B86B 0000000000040000
|
||||
0101010101010101 CAFFC6AC4542DE31 0000000000020000
|
||||
0101010101010101 8DD45A2DDF90796C 0000000000010000
|
||||
0101010101010101 1029D55E880EC2D0 0000000000008000
|
||||
0101010101010101 5D86CB23639DBEA9 0000000000004000
|
||||
0101010101010101 1D1CA853AE7C0C5F 0000000000002000
|
||||
0101010101010101 CE332329248F3228 0000000000001000
|
||||
0101010101010101 8405D1ABE24FB942 0000000000000800
|
||||
0101010101010101 E643D78090CA4207 0000000000000400
|
||||
0101010101010101 48221B9937748A23 0000000000000200
|
||||
0101010101010101 DD7C0BBD61FAFD54 0000000000000100
|
||||
0101010101010101 2FBC291A570DB5C4 0000000000000080
|
||||
0101010101010101 E07C30D7E4E26E12 0000000000000040
|
||||
0101010101010101 0953E2258E8E90A1 0000000000000020
|
||||
0101010101010101 5B711BC4CEEBF2EE 0000000000000010
|
||||
0101010101010101 CC083F1E6D9E85F6 0000000000000008
|
||||
0101010101010101 D2FD8867D50D2DFE 0000000000000004
|
||||
0101010101010101 06E7EA22CE92708F 0000000000000002
|
||||
0101010101010101 166B40B44ABA4BD6 0000000000000001
|
||||
8001010101010101 0000000000000000 95A8D72813DAA94D
|
||||
4001010101010101 0000000000000000 0EEC1487DD8C26D5
|
||||
2001010101010101 0000000000000000 7AD16FFB79C45926
|
||||
1001010101010101 0000000000000000 D3746294CA6A6CF3
|
||||
0801010101010101 0000000000000000 809F5F873C1FD761
|
||||
0401010101010101 0000000000000000 C02FAFFEC989D1FC
|
||||
0201010101010101 0000000000000000 4615AA1D33E72F10
|
||||
0180010101010101 0000000000000000 2055123350C00858
|
||||
0140010101010101 0000000000000000 DF3B99D6577397C8
|
||||
0120010101010101 0000000000000000 31FE17369B5288C9
|
||||
0110010101010101 0000000000000000 DFDD3CC64DAE1642
|
||||
0108010101010101 0000000000000000 178C83CE2B399D94
|
||||
0104010101010101 0000000000000000 50F636324A9B7F80
|
||||
0102010101010101 0000000000000000 A8468EE3BC18F06D
|
||||
0101800101010101 0000000000000000 A2DC9E92FD3CDE92
|
||||
0101400101010101 0000000000000000 CAC09F797D031287
|
||||
0101200101010101 0000000000000000 90BA680B22AEB525
|
||||
0101100101010101 0000000000000000 CE7A24F350E280B6
|
||||
0101080101010101 0000000000000000 882BFF0AA01A0B87
|
||||
0101040101010101 0000000000000000 25610288924511C2
|
||||
0101020101010101 0000000000000000 C71516C29C75D170
|
||||
0101018001010101 0000000000000000 5199C29A52C9F059
|
||||
0101014001010101 0000000000000000 C22F0A294A71F29F
|
||||
0101012001010101 0000000000000000 EE371483714C02EA
|
||||
0101011001010101 0000000000000000 A81FBD448F9E522F
|
||||
0101010801010101 0000000000000000 4F644C92E192DFED
|
||||
0101010401010101 0000000000000000 1AFA9A66A6DF92AE
|
||||
0101010201010101 0000000000000000 B3C1CC715CB879D8
|
||||
0101010180010101 0000000000000000 19D032E64AB0BD8B
|
||||
0101010140010101 0000000000000000 3CFAA7A7DC8720DC
|
||||
0101010120010101 0000000000000000 B7265F7F447AC6F3
|
||||
0101010110010101 0000000000000000 9DB73B3C0D163F54
|
||||
0101010108010101 0000000000000000 8181B65BABF4A975
|
||||
0101010104010101 0000000000000000 93C9B64042EAA240
|
||||
0101010102010101 0000000000000000 5570530829705592
|
||||
0101010101800101 0000000000000000 8638809E878787A0
|
||||
0101010101400101 0000000000000000 41B9A79AF79AC208
|
||||
0101010101200101 0000000000000000 7A9BE42F2009A892
|
||||
0101010101100101 0000000000000000 29038D56BA6D2745
|
||||
0101010101080101 0000000000000000 5495C6ABF1E5DF51
|
||||
0101010101040101 0000000000000000 AE13DBD561488933
|
||||
0101010101020101 0000000000000000 024D1FFA8904E389
|
||||
0101010101018001 0000000000000000 D1399712F99BF02E
|
||||
0101010101014001 0000000000000000 14C1D7C1CFFEC79E
|
||||
0101010101012001 0000000000000000 1DE5279DAE3BED6F
|
||||
0101010101011001 0000000000000000 E941A33F85501303
|
||||
0101010101010801 0000000000000000 DA99DBBC9A03F379
|
||||
0101010101010401 0000000000000000 B7FC92F91D8E92E9
|
||||
0101010101010201 0000000000000000 AE8E5CAA3CA04E85
|
||||
0101010101010180 0000000000000000 9CC62DF43B6EED74
|
||||
0101010101010140 0000000000000000 D863DBB5C59A91A0
|
||||
0101010101010120 0000000000000000 A1AB2190545B91D7
|
||||
0101010101010110 0000000000000000 0875041E64C570F7
|
||||
0101010101010108 0000000000000000 5A594528BEBEF1CC
|
||||
0101010101010104 0000000000000000 FCDB3291DE21F0C0
|
||||
0101010101010102 0000000000000000 869EFD7F9F265A09
|
||||
1046913489980131 0000000000000000 88D55E54F54C97B4
|
||||
1007103489988020 0000000000000000 0C0CC00C83EA48FD
|
||||
10071034C8980120 0000000000000000 83BC8EF3A6570183
|
||||
1046103489988020 0000000000000000 DF725DCAD94EA2E9
|
||||
1086911519190101 0000000000000000 E652B53B550BE8B0
|
||||
1086911519580101 0000000000000000 AF527120C485CBB0
|
||||
5107B01519580101 0000000000000000 0F04CE393DB926D5
|
||||
1007B01519190101 0000000000000000 C9F00FFC74079067
|
||||
3107915498080101 0000000000000000 7CFD82A593252B4E
|
||||
3107919498080101 0000000000000000 CB49A2F9E91363E3
|
||||
10079115B9080140 0000000000000000 00B588BE70D23F56
|
||||
3107911598090140 0000000000000000 406A9A6AB43399AE
|
||||
1007D01589980101 0000000000000000 6CB773611DCA9ADA
|
||||
9107911589980101 0000000000000000 67FD21C17DBB5D70
|
||||
9107D01589190101 0000000000000000 9592CB4110430787
|
||||
1007D01598980120 0000000000000000 A6B7FF68A318DDD3
|
||||
1007940498190101 0000000000000000 4D102196C914CA16
|
||||
0107910491190401 0000000000000000 2DFA9F4573594965
|
||||
0107910491190101 0000000000000000 B46604816C0E0774
|
||||
0107940491190401 0000000000000000 6E7E6221A4F34E87
|
||||
19079210981A0101 0000000000000000 AA85E74643233199
|
||||
1007911998190801 0000000000000000 2E5A19DB4D1962D6
|
||||
10079119981A0801 0000000000000000 23A866A809D30894
|
||||
1007921098190101 0000000000000000 D812D961F017D320
|
||||
100791159819010B 0000000000000000 055605816E58608F
|
||||
1004801598190101 0000000000000000 ABD88E8B1B7716F1
|
||||
1004801598190102 0000000000000000 537AC95BE69DA1E1
|
||||
1004801598190108 0000000000000000 AED0F6AE3C25CDD8
|
||||
1002911598100104 0000000000000000 B3E35A5EE53E7B8D
|
||||
1002911598190104 0000000000000000 61C79C71921A2EF8
|
||||
1002911598100201 0000000000000000 E2F5728F0995013C
|
||||
1002911698100101 0000000000000000 1AEAC39A61F0A464
|
||||
7CA110454A1A6E57 01A1D6D039776742 690F5B0D9A26939B
|
||||
0131D9619DC1376E 5CD54CA83DEF57DA 7A389D10354BD271
|
||||
07A1133E4A0B2686 0248D43806F67172 868EBB51CAB4599A
|
||||
3849674C2602319E 51454B582DDF440A 7178876E01F19B2A
|
||||
04B915BA43FEB5B6 42FD443059577FA2 AF37FB421F8C4095
|
||||
0113B970FD34F2CE 059B5E0851CF143A 86A560F10EC6D85B
|
||||
0170F175468FB5E6 0756D8E0774761D2 0CD3DA020021DC09
|
||||
43297FAD38E373FE 762514B829BF486A EA676B2CB7DB2B7A
|
||||
07A7137045DA2A16 3BDD119049372802 DFD64A815CAF1A0F
|
||||
04689104C2FD3B2F 26955F6835AF609A 5C513C9C4886C088
|
||||
37D06BB516CB7546 164D5E404F275232 0A2AEEAE3FF4AB77
|
||||
1F08260D1AC2465E 6B056E18759F5CCA EF1BF03E5DFA575A
|
||||
584023641ABA6176 004BD6EF09176062 88BF0DB6D70DEE56
|
||||
025816164629B007 480D39006EE762F2 A1F9915541020B56
|
||||
49793EBC79B3258F 437540C8698F3CFA 6FBF1CAFCFFD0556
|
||||
4FB05E1515AB73A7 072D43A077075292 2F22E49BAB7CA1AC
|
||||
49E95D6D4CA229BF 02FE55778117F12A 5A6B612CC26CCE4A
|
||||
018310DC409B26D6 1D9D5C5018F728C2 5F4C038ED12B2E41
|
||||
1C587F1C13924FEF 305532286D6F295A 63FAC0D034D9F793
|
||||
@@ -0,0 +1,90 @@
|
||||
// This file is mostly generated by Phil Karn's gensp.c
|
||||
|
||||
#include "pch.h"
|
||||
#include "des.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
// VC60 workaround: gives a C4786 warning without this function
|
||||
// when runtime lib is set to multithread debug DLL
|
||||
// even though warning 4786 is disabled!
|
||||
void DES_VC60Workaround()
|
||||
{
|
||||
}
|
||||
|
||||
const word32 DES::Base::Spbox[8][64] = {
|
||||
{
|
||||
0x01010400,0x00000000,0x00010000,0x01010404, 0x01010004,0x00010404,0x00000004,0x00010000,
|
||||
0x00000400,0x01010400,0x01010404,0x00000400, 0x01000404,0x01010004,0x01000000,0x00000004,
|
||||
0x00000404,0x01000400,0x01000400,0x00010400, 0x00010400,0x01010000,0x01010000,0x01000404,
|
||||
0x00010004,0x01000004,0x01000004,0x00010004, 0x00000000,0x00000404,0x00010404,0x01000000,
|
||||
0x00010000,0x01010404,0x00000004,0x01010000, 0x01010400,0x01000000,0x01000000,0x00000400,
|
||||
0x01010004,0x00010000,0x00010400,0x01000004, 0x00000400,0x00000004,0x01000404,0x00010404,
|
||||
0x01010404,0x00010004,0x01010000,0x01000404, 0x01000004,0x00000404,0x00010404,0x01010400,
|
||||
0x00000404,0x01000400,0x01000400,0x00000000, 0x00010004,0x00010400,0x00000000,0x01010004},
|
||||
{
|
||||
0x80108020,0x80008000,0x00008000,0x00108020, 0x00100000,0x00000020,0x80100020,0x80008020,
|
||||
0x80000020,0x80108020,0x80108000,0x80000000, 0x80008000,0x00100000,0x00000020,0x80100020,
|
||||
0x00108000,0x00100020,0x80008020,0x00000000, 0x80000000,0x00008000,0x00108020,0x80100000,
|
||||
0x00100020,0x80000020,0x00000000,0x00108000, 0x00008020,0x80108000,0x80100000,0x00008020,
|
||||
0x00000000,0x00108020,0x80100020,0x00100000, 0x80008020,0x80100000,0x80108000,0x00008000,
|
||||
0x80100000,0x80008000,0x00000020,0x80108020, 0x00108020,0x00000020,0x00008000,0x80000000,
|
||||
0x00008020,0x80108000,0x00100000,0x80000020, 0x00100020,0x80008020,0x80000020,0x00100020,
|
||||
0x00108000,0x00000000,0x80008000,0x00008020, 0x80000000,0x80100020,0x80108020,0x00108000},
|
||||
{
|
||||
0x00000208,0x08020200,0x00000000,0x08020008, 0x08000200,0x00000000,0x00020208,0x08000200,
|
||||
0x00020008,0x08000008,0x08000008,0x00020000, 0x08020208,0x00020008,0x08020000,0x00000208,
|
||||
0x08000000,0x00000008,0x08020200,0x00000200, 0x00020200,0x08020000,0x08020008,0x00020208,
|
||||
0x08000208,0x00020200,0x00020000,0x08000208, 0x00000008,0x08020208,0x00000200,0x08000000,
|
||||
0x08020200,0x08000000,0x00020008,0x00000208, 0x00020000,0x08020200,0x08000200,0x00000000,
|
||||
0x00000200,0x00020008,0x08020208,0x08000200, 0x08000008,0x00000200,0x00000000,0x08020008,
|
||||
0x08000208,0x00020000,0x08000000,0x08020208, 0x00000008,0x00020208,0x00020200,0x08000008,
|
||||
0x08020000,0x08000208,0x00000208,0x08020000, 0x00020208,0x00000008,0x08020008,0x00020200},
|
||||
{
|
||||
0x00802001,0x00002081,0x00002081,0x00000080, 0x00802080,0x00800081,0x00800001,0x00002001,
|
||||
0x00000000,0x00802000,0x00802000,0x00802081, 0x00000081,0x00000000,0x00800080,0x00800001,
|
||||
0x00000001,0x00002000,0x00800000,0x00802001, 0x00000080,0x00800000,0x00002001,0x00002080,
|
||||
0x00800081,0x00000001,0x00002080,0x00800080, 0x00002000,0x00802080,0x00802081,0x00000081,
|
||||
0x00800080,0x00800001,0x00802000,0x00802081, 0x00000081,0x00000000,0x00000000,0x00802000,
|
||||
0x00002080,0x00800080,0x00800081,0x00000001, 0x00802001,0x00002081,0x00002081,0x00000080,
|
||||
0x00802081,0x00000081,0x00000001,0x00002000, 0x00800001,0x00002001,0x00802080,0x00800081,
|
||||
0x00002001,0x00002080,0x00800000,0x00802001, 0x00000080,0x00800000,0x00002000,0x00802080},
|
||||
{
|
||||
0x00000100,0x02080100,0x02080000,0x42000100, 0x00080000,0x00000100,0x40000000,0x02080000,
|
||||
0x40080100,0x00080000,0x02000100,0x40080100, 0x42000100,0x42080000,0x00080100,0x40000000,
|
||||
0x02000000,0x40080000,0x40080000,0x00000000, 0x40000100,0x42080100,0x42080100,0x02000100,
|
||||
0x42080000,0x40000100,0x00000000,0x42000000, 0x02080100,0x02000000,0x42000000,0x00080100,
|
||||
0x00080000,0x42000100,0x00000100,0x02000000, 0x40000000,0x02080000,0x42000100,0x40080100,
|
||||
0x02000100,0x40000000,0x42080000,0x02080100, 0x40080100,0x00000100,0x02000000,0x42080000,
|
||||
0x42080100,0x00080100,0x42000000,0x42080100, 0x02080000,0x00000000,0x40080000,0x42000000,
|
||||
0x00080100,0x02000100,0x40000100,0x00080000, 0x00000000,0x40080000,0x02080100,0x40000100},
|
||||
{
|
||||
0x20000010,0x20400000,0x00004000,0x20404010, 0x20400000,0x00000010,0x20404010,0x00400000,
|
||||
0x20004000,0x00404010,0x00400000,0x20000010, 0x00400010,0x20004000,0x20000000,0x00004010,
|
||||
0x00000000,0x00400010,0x20004010,0x00004000, 0x00404000,0x20004010,0x00000010,0x20400010,
|
||||
0x20400010,0x00000000,0x00404010,0x20404000, 0x00004010,0x00404000,0x20404000,0x20000000,
|
||||
0x20004000,0x00000010,0x20400010,0x00404000, 0x20404010,0x00400000,0x00004010,0x20000010,
|
||||
0x00400000,0x20004000,0x20000000,0x00004010, 0x20000010,0x20404010,0x00404000,0x20400000,
|
||||
0x00404010,0x20404000,0x00000000,0x20400010, 0x00000010,0x00004000,0x20400000,0x00404010,
|
||||
0x00004000,0x00400010,0x20004010,0x00000000, 0x20404000,0x20000000,0x00400010,0x20004010},
|
||||
{
|
||||
0x00200000,0x04200002,0x04000802,0x00000000, 0x00000800,0x04000802,0x00200802,0x04200800,
|
||||
0x04200802,0x00200000,0x00000000,0x04000002, 0x00000002,0x04000000,0x04200002,0x00000802,
|
||||
0x04000800,0x00200802,0x00200002,0x04000800, 0x04000002,0x04200000,0x04200800,0x00200002,
|
||||
0x04200000,0x00000800,0x00000802,0x04200802, 0x00200800,0x00000002,0x04000000,0x00200800,
|
||||
0x04000000,0x00200800,0x00200000,0x04000802, 0x04000802,0x04200002,0x04200002,0x00000002,
|
||||
0x00200002,0x04000000,0x04000800,0x00200000, 0x04200800,0x00000802,0x00200802,0x04200800,
|
||||
0x00000802,0x04000002,0x04200802,0x04200000, 0x00200800,0x00000000,0x00000002,0x04200802,
|
||||
0x00000000,0x00200802,0x04200000,0x00000800, 0x04000002,0x04000800,0x00000800,0x00200002},
|
||||
{
|
||||
0x10001040,0x00001000,0x00040000,0x10041040, 0x10000000,0x10001040,0x00000040,0x10000000,
|
||||
0x00040040,0x10040000,0x10041040,0x00041000, 0x10041000,0x00041040,0x00001000,0x00000040,
|
||||
0x10040000,0x10000040,0x10001000,0x00001040, 0x00041000,0x00040040,0x10040040,0x10041000,
|
||||
0x00001040,0x00000000,0x00000000,0x10040040, 0x10000040,0x10001000,0x00041040,0x00040000,
|
||||
0x00041040,0x00040000,0x10041000,0x00001000, 0x00000040,0x10040040,0x00001000,0x00041040,
|
||||
0x10001000,0x00000040,0x10000040,0x10040000, 0x10040040,0x10000000,0x00040000,0x10001040,
|
||||
0x00000000,0x10041040,0x00040040,0x10000040, 0x10040000,0x10001000,0x10001040,0x00000000,
|
||||
0x10041040,0x00041000,0x00041000,0x00001040, 0x00001040,0x00040040,0x10000000,0x10041000}
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -0,0 +1,107 @@
|
||||
// eprecomp.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
#include "eprecomp.h"
|
||||
#include "asn.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
template <class T> void DL_FixedBasePrecomputationImpl<T>::SetBase(const DL_GroupPrecomputation<Element> &group, const Element &i_base)
|
||||
{
|
||||
m_base = group.NeedConversions() ? group.ConvertIn(i_base) : i_base;
|
||||
|
||||
if (m_bases.empty() || !(m_base == m_bases[0]))
|
||||
{
|
||||
m_bases.resize(1);
|
||||
m_bases[0] = m_base;
|
||||
}
|
||||
|
||||
if (group.NeedConversions())
|
||||
m_base = i_base;
|
||||
}
|
||||
|
||||
template <class T> void DL_FixedBasePrecomputationImpl<T>::Precompute(const DL_GroupPrecomputation<Element> &group, unsigned int maxExpBits, unsigned int storage)
|
||||
{
|
||||
assert(m_bases.size() > 0);
|
||||
assert(storage <= maxExpBits);
|
||||
|
||||
if (storage > 1)
|
||||
{
|
||||
m_windowSize = (maxExpBits+storage-1)/storage;
|
||||
m_exponentBase = Integer::Power2(m_windowSize);
|
||||
}
|
||||
|
||||
m_bases.resize(storage);
|
||||
for (unsigned i=1; i<storage; i++)
|
||||
m_bases[i] = group.GetGroup().ScalarMultiply(m_bases[i-1], m_exponentBase);
|
||||
}
|
||||
|
||||
template <class T> void DL_FixedBasePrecomputationImpl<T>::Load(const DL_GroupPrecomputation<Element> &group, BufferedTransformation &bt)
|
||||
{
|
||||
BERSequenceDecoder seq(bt);
|
||||
word32 version;
|
||||
BERDecodeUnsigned<word32>(seq, version, INTEGER, 1, 1);
|
||||
m_exponentBase.BERDecode(seq);
|
||||
m_windowSize = m_exponentBase.BitCount() - 1;
|
||||
m_bases.clear();
|
||||
while (!seq.EndReached())
|
||||
m_bases.push_back(group.BERDecodeElement(seq));
|
||||
if (!m_bases.empty() && group.NeedConversions())
|
||||
m_base = group.ConvertOut(m_bases[0]);
|
||||
seq.MessageEnd();
|
||||
}
|
||||
|
||||
template <class T> void DL_FixedBasePrecomputationImpl<T>::Save(const DL_GroupPrecomputation<Element> &group, BufferedTransformation &bt) const
|
||||
{
|
||||
DERSequenceEncoder seq(bt);
|
||||
DEREncodeUnsigned<word32>(seq, 1); // version
|
||||
m_exponentBase.DEREncode(seq);
|
||||
for (unsigned i=0; i<m_bases.size(); i++)
|
||||
group.DEREncodeElement(seq, m_bases[i]);
|
||||
seq.MessageEnd();
|
||||
}
|
||||
|
||||
template <class T> void DL_FixedBasePrecomputationImpl<T>::PrepareCascade(const DL_GroupPrecomputation<Element> &i_group, std::vector<BaseAndExponent<Element> > &eb, const Integer &exponent) const
|
||||
{
|
||||
const AbstractGroup<T> &group = i_group.GetGroup();
|
||||
|
||||
Integer r, q, e = exponent;
|
||||
bool fastNegate = group.InversionIsFast() && m_windowSize > 1;
|
||||
unsigned int i;
|
||||
|
||||
for (i=0; i+1<m_bases.size(); i++)
|
||||
{
|
||||
Integer::DivideByPowerOf2(r, q, e, m_windowSize);
|
||||
std::swap(q, e);
|
||||
if (fastNegate && r.GetBit(m_windowSize-1))
|
||||
{
|
||||
++e;
|
||||
eb.push_back(BaseAndExponent<Element>(group.Inverse(m_bases[i]), m_exponentBase - r));
|
||||
}
|
||||
else
|
||||
eb.push_back(BaseAndExponent<Element>(m_bases[i], r));
|
||||
}
|
||||
eb.push_back(BaseAndExponent<Element>(m_bases[i], e));
|
||||
}
|
||||
|
||||
template <class T> T DL_FixedBasePrecomputationImpl<T>::Exponentiate(const DL_GroupPrecomputation<Element> &group, const Integer &exponent) const
|
||||
{
|
||||
std::vector<BaseAndExponent<Element> > eb; // array of segments of the exponent and precalculated bases
|
||||
eb.reserve(m_bases.size());
|
||||
PrepareCascade(group, eb, exponent);
|
||||
return group.ConvertOut(GeneralCascadeMultiplication<Element>(group.GetGroup(), eb.begin(), eb.end()));
|
||||
}
|
||||
|
||||
template <class T> T
|
||||
DL_FixedBasePrecomputationImpl<T>::CascadeExponentiate(const DL_GroupPrecomputation<Element> &group, const Integer &exponent,
|
||||
const DL_FixedBasePrecomputation<T> &i_pc2, const Integer &exponent2) const
|
||||
{
|
||||
std::vector<BaseAndExponent<Element> > eb; // array of segments of the exponent and precalculated bases
|
||||
const DL_FixedBasePrecomputationImpl<T> &pc2 = static_cast<const DL_FixedBasePrecomputationImpl<T> &>(i_pc2);
|
||||
eb.reserve(m_bases.size() + pc2.m_bases.size());
|
||||
PrepareCascade(group, eb, exponent);
|
||||
pc2.PrepareCascade(group, eb, exponent2);
|
||||
return group.ConvertOut(GeneralCascadeMultiplication<Element>(group.GetGroup(), eb.begin(), eb.end()));
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -0,0 +1,69 @@
|
||||
#ifndef CRYPTOPP_EPRECOMP_H
|
||||
#define CRYPTOPP_EPRECOMP_H
|
||||
|
||||
#include "integer.h"
|
||||
#include "algebra.h"
|
||||
#include <vector>
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
template <class T>
|
||||
class DL_GroupPrecomputation
|
||||
{
|
||||
public:
|
||||
typedef T Element;
|
||||
|
||||
virtual bool NeedConversions() const {return false;}
|
||||
virtual Element ConvertIn(const Element &v) const {return v;}
|
||||
virtual Element ConvertOut(const Element &v) const {return v;}
|
||||
virtual const AbstractGroup<Element> & GetGroup() const =0;
|
||||
virtual Element BERDecodeElement(BufferedTransformation &bt) const =0;
|
||||
virtual void DEREncodeElement(BufferedTransformation &bt, const Element &P) const =0;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class DL_FixedBasePrecomputation
|
||||
{
|
||||
public:
|
||||
typedef T Element;
|
||||
|
||||
virtual bool IsInitialized() const =0;
|
||||
virtual void SetBase(const DL_GroupPrecomputation<Element> &group, const Element &base) =0;
|
||||
virtual const Element & GetBase(const DL_GroupPrecomputation<Element> &group) const =0;
|
||||
virtual void Precompute(const DL_GroupPrecomputation<Element> &group, unsigned int maxExpBits, unsigned int storage) =0;
|
||||
virtual void Load(const DL_GroupPrecomputation<Element> &group, BufferedTransformation &storedPrecomputation) =0;
|
||||
virtual void Save(const DL_GroupPrecomputation<Element> &group, BufferedTransformation &storedPrecomputation) const =0;
|
||||
virtual Element Exponentiate(const DL_GroupPrecomputation<Element> &group, const Integer &exponent) const =0;
|
||||
virtual Element CascadeExponentiate(const DL_GroupPrecomputation<Element> &group, const Integer &exponent, const DL_FixedBasePrecomputation<Element> &pc2, const Integer &exponent2) const =0;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class DL_FixedBasePrecomputationImpl : public DL_FixedBasePrecomputation<T>
|
||||
{
|
||||
public:
|
||||
typedef T Element;
|
||||
|
||||
// DL_FixedBasePrecomputation
|
||||
bool IsInitialized() const
|
||||
{return !m_bases.empty();}
|
||||
void SetBase(const DL_GroupPrecomputation<Element> &group, const Element &base);
|
||||
const Element & GetBase(const DL_GroupPrecomputation<Element> &group) const
|
||||
{return group.NeedConversions() ? m_base : m_bases[0];}
|
||||
void Precompute(const DL_GroupPrecomputation<Element> &group, unsigned int maxExpBits, unsigned int storage);
|
||||
void Load(const DL_GroupPrecomputation<Element> &group, BufferedTransformation &storedPrecomputation);
|
||||
void Save(const DL_GroupPrecomputation<Element> &group, BufferedTransformation &storedPrecomputation) const;
|
||||
Element Exponentiate(const DL_GroupPrecomputation<Element> &group, const Integer &exponent) const;
|
||||
Element CascadeExponentiate(const DL_GroupPrecomputation<Element> &group, const Integer &exponent, const DL_FixedBasePrecomputation<Element> &pc2, const Integer &exponent2) const;
|
||||
|
||||
private:
|
||||
void PrepareCascade(const DL_GroupPrecomputation<Element> &group, std::vector<BaseAndExponent<Element> > &eb, const Integer &exponent) const;
|
||||
|
||||
Element m_base;
|
||||
unsigned int m_windowSize;
|
||||
Integer m_exponentBase; // what base to represent the exponent in
|
||||
std::vector<Element> m_bases; // precalculated bases
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,186 @@
|
||||
// files.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
#include "files.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
using namespace std;
|
||||
|
||||
void Files_TestInstantiations()
|
||||
{
|
||||
FileStore f0;
|
||||
FileSource f1;
|
||||
FileSink f2;
|
||||
}
|
||||
|
||||
void FileStore::StoreInitialize(const NameValuePairs ¶meters)
|
||||
{
|
||||
const char *fileName;
|
||||
if (parameters.GetValue("InputFileName", fileName))
|
||||
{
|
||||
ios::openmode binary = parameters.GetValueWithDefault("InputBinaryMode", true) ? ios::binary : ios::openmode(0);
|
||||
m_file.open(fileName, ios::in | binary);
|
||||
if (!m_file)
|
||||
throw OpenErr(fileName);
|
||||
m_stream = &m_file;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_stream = NULL;
|
||||
parameters.GetValue("InputStreamPointer", m_stream);
|
||||
}
|
||||
m_waiting = false;
|
||||
}
|
||||
|
||||
unsigned long FileStore::MaxRetrievable() const
|
||||
{
|
||||
if (!m_stream)
|
||||
return 0;
|
||||
|
||||
streampos current = m_stream->tellg();
|
||||
streampos end = m_stream->seekg(0, ios::end).tellg();
|
||||
m_stream->seekg(current);
|
||||
return end-current;
|
||||
}
|
||||
|
||||
unsigned int FileStore::TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel, bool blocking)
|
||||
{
|
||||
if (!m_stream)
|
||||
{
|
||||
transferBytes = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned long size=transferBytes;
|
||||
transferBytes = 0;
|
||||
|
||||
if (m_waiting)
|
||||
goto output;
|
||||
|
||||
while (size && m_stream->good())
|
||||
{
|
||||
{
|
||||
unsigned int spaceSize = 1024;
|
||||
m_space = HelpCreatePutSpace(target, channel, 1, (unsigned int)STDMIN(size, (unsigned long)UINT_MAX), spaceSize);
|
||||
|
||||
m_stream->read((char *)m_space, STDMIN(size, (unsigned long)spaceSize));
|
||||
}
|
||||
m_len = m_stream->gcount();
|
||||
unsigned int blockedBytes;
|
||||
output:
|
||||
blockedBytes = target.ChannelPutModifiable2(channel, m_space, m_len, 0, blocking);
|
||||
m_waiting = blockedBytes > 0;
|
||||
if (m_waiting)
|
||||
return blockedBytes;
|
||||
size -= m_len;
|
||||
transferBytes += m_len;
|
||||
}
|
||||
|
||||
if (!m_stream->good() && !m_stream->eof())
|
||||
throw ReadErr();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int FileStore::CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end, const std::string &channel, bool blocking) const
|
||||
{
|
||||
if (!m_stream)
|
||||
return 0;
|
||||
|
||||
if (begin == 0 && end == 1)
|
||||
{
|
||||
int result = m_stream->peek();
|
||||
if (result == EOF) // GCC workaround: 2.95.2 doesn't have char_traits<char>::eof()
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
unsigned int blockedBytes = target.ChannelPut(channel, byte(result), blocking);
|
||||
begin += 1-blockedBytes;
|
||||
return blockedBytes;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: figure out what happens on cin
|
||||
streampos current = m_stream->tellg();
|
||||
streampos endPosition = m_stream->seekg(0, ios::end).tellg();
|
||||
streampos newPosition = current + (streamoff)begin;
|
||||
|
||||
if (newPosition >= endPosition)
|
||||
{
|
||||
m_stream->seekg(current);
|
||||
return 0; // don't try to seek beyond the end of file
|
||||
}
|
||||
m_stream->seekg(newPosition);
|
||||
unsigned long total = 0;
|
||||
try
|
||||
{
|
||||
assert(!m_waiting);
|
||||
unsigned long copyMax = end-begin;
|
||||
unsigned int blockedBytes = const_cast<FileStore *>(this)->TransferTo2(target, copyMax, channel, blocking);
|
||||
begin += copyMax;
|
||||
if (blockedBytes)
|
||||
{
|
||||
const_cast<FileStore *>(this)->m_waiting = false;
|
||||
return blockedBytes;
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
m_stream->clear();
|
||||
m_stream->seekg(current);
|
||||
throw;
|
||||
}
|
||||
m_stream->clear();
|
||||
m_stream->seekg(current);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FileSink::IsolatedInitialize(const NameValuePairs ¶meters)
|
||||
{
|
||||
const char *fileName;
|
||||
if (parameters.GetValue("OutputFileName", fileName))
|
||||
{
|
||||
ios::openmode binary = parameters.GetValueWithDefault("OutputBinaryMode", true) ? ios::binary : ios::openmode(0);
|
||||
m_file.open(fileName, ios::out | ios::trunc | binary);
|
||||
if (!m_file)
|
||||
throw OpenErr(fileName);
|
||||
m_stream = &m_file;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_stream = NULL;
|
||||
parameters.GetValue("OutputStreamPointer", m_stream);
|
||||
}
|
||||
}
|
||||
|
||||
bool FileSink::IsolatedFlush(bool hardFlush, bool blocking)
|
||||
{
|
||||
if (!m_stream)
|
||||
throw Err("FileSink: output stream not opened");
|
||||
|
||||
m_stream->flush();
|
||||
if (!m_stream->good())
|
||||
throw WriteErr();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int FileSink::Put2(const byte *inString, unsigned int length, int messageEnd, bool blocking)
|
||||
{
|
||||
if (!m_stream)
|
||||
throw Err("FileSink: output stream not opened");
|
||||
|
||||
m_stream->write((const char *)inString, length);
|
||||
|
||||
if (messageEnd)
|
||||
m_stream->flush();
|
||||
|
||||
if (!m_stream->good())
|
||||
throw WriteErr();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -0,0 +1,95 @@
|
||||
#ifndef CRYPTOPP_FILES_H
|
||||
#define CRYPTOPP_FILES_H
|
||||
|
||||
#include "cryptlib.h"
|
||||
#include "filters.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
//! .
|
||||
class FileStore : public Store, private FilterPutSpaceHelper
|
||||
{
|
||||
public:
|
||||
class Err : public Exception
|
||||
{
|
||||
public:
|
||||
Err(const std::string &s) : Exception(IO_ERROR, s) {}
|
||||
};
|
||||
class OpenErr : public Err {public: OpenErr(const std::string &filename) : Err("FileStore: error opening file for reading: " + filename) {}};
|
||||
class ReadErr : public Err {public: ReadErr() : Err("FileStore: error reading file") {}};
|
||||
|
||||
FileStore() : m_stream(NULL) {}
|
||||
FileStore(std::istream &in)
|
||||
{StoreInitialize(MakeParameters("InputStreamPointer", &in));}
|
||||
FileStore(const char *filename)
|
||||
{StoreInitialize(MakeParameters("InputFileName", filename));}
|
||||
|
||||
std::istream* GetStream() {return m_stream;}
|
||||
|
||||
unsigned long MaxRetrievable() const;
|
||||
unsigned int TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel=NULL_CHANNEL, bool blocking=true);
|
||||
unsigned int CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end=ULONG_MAX, const std::string &channel=NULL_CHANNEL, bool blocking=true) const;
|
||||
|
||||
private:
|
||||
void StoreInitialize(const NameValuePairs ¶meters);
|
||||
|
||||
std::ifstream m_file;
|
||||
std::istream *m_stream;
|
||||
byte *m_space;
|
||||
unsigned int m_len;
|
||||
bool m_waiting;
|
||||
};
|
||||
|
||||
//! .
|
||||
class FileSource : public SourceTemplate<FileStore>
|
||||
{
|
||||
public:
|
||||
typedef FileStore::Err Err;
|
||||
typedef FileStore::OpenErr OpenErr;
|
||||
typedef FileStore::ReadErr ReadErr;
|
||||
|
||||
FileSource(BufferedTransformation *attachment = NULL)
|
||||
: SourceTemplate<FileStore>(attachment) {}
|
||||
FileSource(std::istream &in, bool pumpAll, BufferedTransformation *attachment = NULL)
|
||||
: SourceTemplate<FileStore>(attachment) {SourceInitialize(pumpAll, MakeParameters("InputStreamPointer", &in));}
|
||||
FileSource(const char *filename, bool pumpAll, BufferedTransformation *attachment = NULL, bool binary=true)
|
||||
: SourceTemplate<FileStore>(attachment) {SourceInitialize(pumpAll, MakeParameters("InputFileName", filename)("InputBinaryMode", binary));}
|
||||
|
||||
std::istream* GetStream() {return m_store.GetStream();}
|
||||
};
|
||||
|
||||
//! .
|
||||
class FileSink : public Sink
|
||||
{
|
||||
public:
|
||||
class Err : public Exception
|
||||
{
|
||||
public:
|
||||
Err(const std::string &s) : Exception(IO_ERROR, s) {}
|
||||
};
|
||||
class OpenErr : public Err {public: OpenErr(const std::string &filename) : Err("FileSink: error opening file for writing: " + filename) {}};
|
||||
class WriteErr : public Err {public: WriteErr() : Err("FileSink: error writing file") {}};
|
||||
|
||||
FileSink() : m_stream(NULL) {}
|
||||
FileSink(std::ostream &out)
|
||||
{IsolatedInitialize(MakeParameters("OutputStreamPointer", &out));}
|
||||
FileSink(const char *filename, bool binary=true)
|
||||
{IsolatedInitialize(MakeParameters("OutputFileName", filename)("OutputBinaryMode", binary));}
|
||||
|
||||
std::ostream* GetStream() {return m_stream;}
|
||||
|
||||
void IsolatedInitialize(const NameValuePairs ¶meters);
|
||||
unsigned int Put2(const byte *inString, unsigned int length, int messageEnd, bool blocking);
|
||||
bool IsolatedFlush(bool hardFlush, bool blocking);
|
||||
|
||||
private:
|
||||
std::ofstream m_file;
|
||||
std::ostream *m_stream;
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,897 @@
|
||||
// filters.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
#include "filters.h"
|
||||
#include "mqueue.h"
|
||||
#include "fltrimpl.h"
|
||||
#include "argnames.h"
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
Filter::Filter(BufferedTransformation *attachment)
|
||||
: m_attachment(attachment), m_continueAt(0)
|
||||
{
|
||||
}
|
||||
|
||||
BufferedTransformation * Filter::NewDefaultAttachment() const
|
||||
{
|
||||
return new MessageQueue;
|
||||
}
|
||||
|
||||
BufferedTransformation * Filter::AttachedTransformation()
|
||||
{
|
||||
if (m_attachment.get() == NULL)
|
||||
m_attachment.reset(NewDefaultAttachment());
|
||||
return m_attachment.get();
|
||||
}
|
||||
|
||||
const BufferedTransformation *Filter::AttachedTransformation() const
|
||||
{
|
||||
if (m_attachment.get() == NULL)
|
||||
const_cast<Filter *>(this)->m_attachment.reset(NewDefaultAttachment());
|
||||
return m_attachment.get();
|
||||
}
|
||||
|
||||
void Filter::Detach(BufferedTransformation *newOut)
|
||||
{
|
||||
m_attachment.reset(newOut);
|
||||
NotifyAttachmentChange();
|
||||
}
|
||||
|
||||
void Filter::Insert(Filter *filter)
|
||||
{
|
||||
filter->m_attachment.reset(m_attachment.release());
|
||||
m_attachment.reset(filter);
|
||||
NotifyAttachmentChange();
|
||||
}
|
||||
|
||||
unsigned int Filter::CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end, const std::string &channel, bool blocking) const
|
||||
{
|
||||
return AttachedTransformation()->CopyRangeTo2(target, begin, end, channel, blocking);
|
||||
}
|
||||
|
||||
unsigned int Filter::TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel, bool blocking)
|
||||
{
|
||||
return AttachedTransformation()->TransferTo2(target, transferBytes, channel, blocking);
|
||||
}
|
||||
|
||||
void Filter::Initialize(const NameValuePairs ¶meters, int propagation)
|
||||
{
|
||||
m_continueAt = 0;
|
||||
IsolatedInitialize(parameters);
|
||||
PropagateInitialize(parameters, propagation);
|
||||
}
|
||||
|
||||
bool Filter::Flush(bool hardFlush, int propagation, bool blocking)
|
||||
{
|
||||
switch (m_continueAt)
|
||||
{
|
||||
case 0:
|
||||
if (IsolatedFlush(hardFlush, blocking))
|
||||
return true;
|
||||
case 1:
|
||||
if (OutputFlush(1, hardFlush, propagation, blocking))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Filter::MessageSeriesEnd(int propagation, bool blocking)
|
||||
{
|
||||
switch (m_continueAt)
|
||||
{
|
||||
case 0:
|
||||
if (IsolatedMessageSeriesEnd(blocking))
|
||||
return true;
|
||||
case 1:
|
||||
if (ShouldPropagateMessageSeriesEnd() && OutputMessageSeriesEnd(1, propagation, blocking))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Filter::PropagateInitialize(const NameValuePairs ¶meters, int propagation, const std::string &channel)
|
||||
{
|
||||
if (propagation)
|
||||
AttachedTransformation()->ChannelInitialize(channel, parameters, propagation-1);
|
||||
}
|
||||
|
||||
unsigned int Filter::Output(int outputSite, const byte *inString, unsigned int length, int messageEnd, bool blocking, const std::string &channel)
|
||||
{
|
||||
if (messageEnd)
|
||||
messageEnd--;
|
||||
unsigned int result = AttachedTransformation()->Put2(inString, length, messageEnd, blocking);
|
||||
m_continueAt = result ? outputSite : 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Filter::OutputFlush(int outputSite, bool hardFlush, int propagation, bool blocking, const std::string &channel)
|
||||
{
|
||||
if (propagation && AttachedTransformation()->ChannelFlush(channel, hardFlush, propagation-1, blocking))
|
||||
{
|
||||
m_continueAt = outputSite;
|
||||
return true;
|
||||
}
|
||||
m_continueAt = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Filter::OutputMessageSeriesEnd(int outputSite, int propagation, bool blocking, const std::string &channel)
|
||||
{
|
||||
if (propagation && AttachedTransformation()->ChannelMessageSeriesEnd(channel, propagation-1, blocking))
|
||||
{
|
||||
m_continueAt = outputSite;
|
||||
return true;
|
||||
}
|
||||
m_continueAt = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
|
||||
unsigned int MeterFilter::Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking)
|
||||
{
|
||||
if (m_transparent)
|
||||
{
|
||||
FILTER_BEGIN;
|
||||
m_currentMessageBytes += length;
|
||||
m_totalBytes += length;
|
||||
|
||||
if (messageEnd)
|
||||
{
|
||||
m_currentMessageBytes = 0;
|
||||
m_currentSeriesMessages++;
|
||||
m_totalMessages++;
|
||||
}
|
||||
|
||||
FILTER_OUTPUT(1, begin, length, messageEnd);
|
||||
FILTER_END_NO_MESSAGE_END;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool MeterFilter::IsolatedMessageSeriesEnd(bool blocking)
|
||||
{
|
||||
m_currentMessageBytes = 0;
|
||||
m_currentSeriesMessages = 0;
|
||||
m_totalMessageSeries++;
|
||||
return false;
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
|
||||
void FilterWithBufferedInput::BlockQueue::ResetQueue(unsigned int blockSize, unsigned int maxBlocks)
|
||||
{
|
||||
m_buffer.New(blockSize * maxBlocks);
|
||||
m_blockSize = blockSize;
|
||||
m_maxBlocks = maxBlocks;
|
||||
m_size = 0;
|
||||
m_begin = m_buffer;
|
||||
}
|
||||
|
||||
byte *FilterWithBufferedInput::BlockQueue::GetBlock()
|
||||
{
|
||||
if (m_size >= m_blockSize)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
byte *FilterWithBufferedInput::BlockQueue::GetContigousBlocks(unsigned int &numberOfBytes)
|
||||
{
|
||||
numberOfBytes = STDMIN(numberOfBytes, STDMIN((unsigned int)(m_buffer.end()-m_begin), m_size));
|
||||
byte *ptr = m_begin;
|
||||
m_begin += numberOfBytes;
|
||||
m_size -= numberOfBytes;
|
||||
if (m_size == 0 || m_begin == m_buffer.end())
|
||||
m_begin = m_buffer;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
unsigned int FilterWithBufferedInput::BlockQueue::GetAll(byte *outString)
|
||||
{
|
||||
unsigned int size = m_size;
|
||||
unsigned int numberOfBytes = m_maxBlocks*m_blockSize;
|
||||
const byte *ptr = GetContigousBlocks(numberOfBytes);
|
||||
memcpy(outString, ptr, numberOfBytes);
|
||||
memcpy(outString+numberOfBytes, 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 < (unsigned int)(m_buffer.end()-m_begin)) ? m_begin + m_size : m_begin + m_size - m_buffer.size();
|
||||
unsigned int len = STDMIN(length, (unsigned int)(m_buffer.end()-end));
|
||||
memcpy(end, inString, len);
|
||||
if (len < length)
|
||||
memcpy(m_buffer, inString+len, length-len);
|
||||
m_size += length;
|
||||
}
|
||||
|
||||
FilterWithBufferedInput::FilterWithBufferedInput(BufferedTransformation *attachment)
|
||||
: Filter(attachment)
|
||||
{
|
||||
}
|
||||
|
||||
FilterWithBufferedInput::FilterWithBufferedInput(unsigned int firstSize, unsigned int blockSize, unsigned int lastSize, BufferedTransformation *attachment)
|
||||
: Filter(attachment), m_firstSize(firstSize), m_blockSize(blockSize), m_lastSize(lastSize)
|
||||
, m_firstInputDone(false)
|
||||
{
|
||||
if (m_firstSize < 0 || m_blockSize < 1 || m_lastSize < 0)
|
||||
throw InvalidArgument("FilterWithBufferedInput: invalid buffer size");
|
||||
|
||||
m_queue.ResetQueue(1, m_firstSize);
|
||||
}
|
||||
|
||||
void FilterWithBufferedInput::IsolatedInitialize(const NameValuePairs ¶meters)
|
||||
{
|
||||
InitializeDerivedAndReturnNewSizes(parameters, m_firstSize, m_blockSize, m_lastSize);
|
||||
if (m_firstSize < 0 || m_blockSize < 1 || m_lastSize < 0)
|
||||
throw InvalidArgument("FilterWithBufferedInput: invalid buffer size");
|
||||
m_queue.ResetQueue(1, m_firstSize);
|
||||
m_firstInputDone = false;
|
||||
}
|
||||
|
||||
bool FilterWithBufferedInput::IsolatedFlush(bool hardFlush, bool blocking)
|
||||
{
|
||||
if (!blocking)
|
||||
throw BlockingInputOnly("FilterWithBufferedInput");
|
||||
|
||||
if (hardFlush)
|
||||
ForceNextPut();
|
||||
FlushDerived();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int FilterWithBufferedInput::PutMaybeModifiable(byte *inString, unsigned int length, int messageEnd, bool blocking, bool modifiable)
|
||||
{
|
||||
if (!blocking)
|
||||
throw BlockingInputOnly("FilterWithBufferedInput");
|
||||
|
||||
if (length != 0)
|
||||
{
|
||||
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;
|
||||
byte *ptr = m_queue.GetContigousBlocks(len);
|
||||
NextPutModifiable(ptr, len);
|
||||
newLength -= len;
|
||||
}
|
||||
|
||||
if (newLength > m_lastSize)
|
||||
{
|
||||
unsigned int len = newLength - m_lastSize;
|
||||
NextPutMaybeModifiable(inString, len, modifiable);
|
||||
inString += len;
|
||||
newLength -= len;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (newLength >= m_blockSize + m_lastSize && m_queue.CurrentSize() >= m_blockSize)
|
||||
{
|
||||
NextPutModifiable(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;
|
||||
NextPutModifiable(m_queue.GetBlock(), m_blockSize);
|
||||
newLength -= m_blockSize;
|
||||
}
|
||||
|
||||
if (newLength >= m_blockSize + m_lastSize)
|
||||
{
|
||||
unsigned int len = RoundDownToMultipleOf(newLength - m_lastSize, m_blockSize);
|
||||
NextPutMaybeModifiable(inString, len, modifiable);
|
||||
inString += len;
|
||||
newLength -= len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_queue.Put(inString, newLength - m_queue.CurrentSize());
|
||||
}
|
||||
|
||||
if (messageEnd)
|
||||
{
|
||||
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);
|
||||
|
||||
Output(1, NULL, 0, messageEnd, blocking);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FilterWithBufferedInput::ForceNextPut()
|
||||
{
|
||||
if (!m_firstInputDone)
|
||||
return;
|
||||
|
||||
if (m_blockSize > 1)
|
||||
{
|
||||
while (m_queue.CurrentSize() >= m_blockSize)
|
||||
NextPutModifiable(m_queue.GetBlock(), m_blockSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int len;
|
||||
while ((len = m_queue.CurrentSize()) > 0)
|
||||
NextPutModifiable(m_queue.GetContigousBlocks(len), len);
|
||||
}
|
||||
}
|
||||
|
||||
void FilterWithBufferedInput::NextPutMultiple(const byte *inString, unsigned int length)
|
||||
{
|
||||
assert(m_blockSize > 1); // m_blockSize = 1 should always override this function
|
||||
while (length > 0)
|
||||
{
|
||||
assert(length >= m_blockSize);
|
||||
NextPutSingle(inString);
|
||||
inString += m_blockSize;
|
||||
length -= m_blockSize;
|
||||
}
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
|
||||
void Redirector::ChannelInitialize(const std::string &channel, const NameValuePairs ¶meters, int propagation)
|
||||
{
|
||||
if (channel.empty())
|
||||
{
|
||||
m_target = parameters.GetValueWithDefault("RedirectionTargetPointer", (BufferedTransformation*)NULL);
|
||||
m_passSignal = parameters.GetValueWithDefault("PassSignal", true);
|
||||
}
|
||||
|
||||
if (m_target && m_passSignal)
|
||||
m_target->ChannelInitialize(channel, parameters, propagation);
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
|
||||
ProxyFilter::ProxyFilter(BufferedTransformation *filter, unsigned int firstSize, unsigned int lastSize, BufferedTransformation *attachment)
|
||||
: FilterWithBufferedInput(firstSize, 1, lastSize, attachment), m_filter(filter)
|
||||
{
|
||||
if (m_filter.get())
|
||||
m_filter->Attach(new OutputProxy(*this, false));
|
||||
}
|
||||
|
||||
bool ProxyFilter::IsolatedFlush(bool hardFlush, bool blocking)
|
||||
{
|
||||
return m_filter.get() ? m_filter->Flush(hardFlush, -1, blocking) : false;
|
||||
}
|
||||
|
||||
void ProxyFilter::SetFilter(Filter *filter)
|
||||
{
|
||||
m_filter.reset(filter);
|
||||
if (filter)
|
||||
{
|
||||
OutputProxy *proxy;
|
||||
std::auto_ptr<OutputProxy> temp(proxy = new OutputProxy(*this, false));
|
||||
m_filter->TransferAllTo(*proxy);
|
||||
m_filter->Attach(temp.release());
|
||||
}
|
||||
}
|
||||
|
||||
void ProxyFilter::NextPutMultiple(const byte *s, unsigned int len)
|
||||
{
|
||||
if (m_filter.get())
|
||||
m_filter->Put(s, len);
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
|
||||
unsigned int ArraySink::Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking)
|
||||
{
|
||||
memcpy(m_buf+m_total, begin, STDMIN(length, SaturatingSubtract(m_size, m_total)));
|
||||
m_total += length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
byte * ArraySink::CreatePutSpace(unsigned int &size)
|
||||
{
|
||||
size = m_size - m_total;
|
||||
return m_buf + m_total;
|
||||
}
|
||||
|
||||
void ArraySink::IsolatedInitialize(const NameValuePairs ¶meters)
|
||||
{
|
||||
ByteArrayParameter array;
|
||||
if (!parameters.GetValue(Name::OutputBuffer(), array))
|
||||
throw InvalidArgument("ArraySink: missing OutputBuffer argument");
|
||||
m_buf = array.begin();
|
||||
m_size = array.size();
|
||||
m_total = 0;
|
||||
}
|
||||
|
||||
unsigned int ArrayXorSink::Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking)
|
||||
{
|
||||
xorbuf(m_buf+m_total, begin, STDMIN(length, SaturatingSubtract(m_size, m_total)));
|
||||
m_total += length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
|
||||
unsigned int StreamTransformationFilter::LastBlockSize(StreamTransformation &c, BlockPaddingScheme padding)
|
||||
{
|
||||
if (c.MinLastBlockSize() > 0)
|
||||
return c.MinLastBlockSize();
|
||||
else if (c.MandatoryBlockSize() > 1 && !c.IsForwardTransformation() && padding != NO_PADDING && padding != ZEROS_PADDING)
|
||||
return c.MandatoryBlockSize();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
StreamTransformationFilter::StreamTransformationFilter(StreamTransformation &c, BufferedTransformation *attachment, BlockPaddingScheme padding)
|
||||
: FilterWithBufferedInput(0, c.MandatoryBlockSize(), LastBlockSize(c, padding), attachment)
|
||||
, m_cipher(c)
|
||||
{
|
||||
assert(c.MinLastBlockSize() == 0 || c.MinLastBlockSize() > c.MandatoryBlockSize());
|
||||
|
||||
bool isBlockCipher = (c.MandatoryBlockSize() > 1 && c.MinLastBlockSize() == 0);
|
||||
|
||||
if (padding == DEFAULT_PADDING)
|
||||
{
|
||||
if (isBlockCipher)
|
||||
m_padding = PKCS_PADDING;
|
||||
else
|
||||
m_padding = NO_PADDING;
|
||||
}
|
||||
else
|
||||
m_padding = padding;
|
||||
|
||||
if (!isBlockCipher && (m_padding == PKCS_PADDING || m_padding == ONE_AND_ZEROS_PADDING))
|
||||
throw InvalidArgument("StreamTransformationFilter: PKCS_PADDING and ONE_AND_ZEROS_PADDING cannot be used with " + c.AlgorithmName());
|
||||
}
|
||||
|
||||
void StreamTransformationFilter::FirstPut(const byte *inString)
|
||||
{
|
||||
m_optimalBufferSize = m_cipher.OptimalBlockSize();
|
||||
m_optimalBufferSize = STDMAX(m_optimalBufferSize, RoundDownToMultipleOf(4096U, m_optimalBufferSize));
|
||||
}
|
||||
|
||||
void StreamTransformationFilter::NextPutMultiple(const byte *inString, unsigned int length)
|
||||
{
|
||||
if (!length)
|
||||
return;
|
||||
|
||||
unsigned int s = m_cipher.MandatoryBlockSize();
|
||||
|
||||
do
|
||||
{
|
||||
unsigned int len = m_optimalBufferSize;
|
||||
byte *space = HelpCreatePutSpace(*AttachedTransformation(), NULL_CHANNEL, s, length, len);
|
||||
if (len < length)
|
||||
{
|
||||
if (len == m_optimalBufferSize)
|
||||
len -= m_cipher.GetOptimalBlockSizeUsed();
|
||||
len = RoundDownToMultipleOf(len, s);
|
||||
}
|
||||
else
|
||||
len = length;
|
||||
m_cipher.ProcessString(space, inString, len);
|
||||
AttachedTransformation()->PutModifiable(space, len);
|
||||
inString += len;
|
||||
length -= len;
|
||||
}
|
||||
while (length > 0);
|
||||
}
|
||||
|
||||
void StreamTransformationFilter::NextPutModifiable(byte *inString, unsigned int length)
|
||||
{
|
||||
m_cipher.ProcessString(inString, length);
|
||||
AttachedTransformation()->PutModifiable(inString, length);
|
||||
}
|
||||
|
||||
void StreamTransformationFilter::LastPut(const byte *inString, unsigned int length)
|
||||
{
|
||||
byte *space = NULL;
|
||||
|
||||
switch (m_padding)
|
||||
{
|
||||
case NO_PADDING:
|
||||
case ZEROS_PADDING:
|
||||
if (length > 0)
|
||||
{
|
||||
unsigned int minLastBlockSize = m_cipher.MinLastBlockSize();
|
||||
bool isForwardTransformation = m_cipher.IsForwardTransformation();
|
||||
|
||||
if (isForwardTransformation && m_padding == ZEROS_PADDING && (minLastBlockSize == 0 || length < minLastBlockSize))
|
||||
{
|
||||
// do padding
|
||||
unsigned int blockSize = STDMAX(minLastBlockSize, m_cipher.MandatoryBlockSize());
|
||||
space = HelpCreatePutSpace(*AttachedTransformation(), NULL_CHANNEL, blockSize);
|
||||
memcpy(space, inString, length);
|
||||
memset(space + length, 0, blockSize - length);
|
||||
m_cipher.ProcessLastBlock(space, space, blockSize);
|
||||
AttachedTransformation()->Put(space, blockSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (minLastBlockSize == 0)
|
||||
{
|
||||
if (isForwardTransformation)
|
||||
throw InvalidDataFormat("StreamTransformationFilter: plaintext length is not a multiple of block size and NO_PADDING is specified");
|
||||
else
|
||||
throw InvalidCiphertext("StreamTransformationFilter: ciphertext length is not a multiple of block size");
|
||||
}
|
||||
|
||||
space = HelpCreatePutSpace(*AttachedTransformation(), NULL_CHANNEL, length, m_optimalBufferSize);
|
||||
m_cipher.ProcessLastBlock(space, inString, length);
|
||||
AttachedTransformation()->Put(space, length);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PKCS_PADDING:
|
||||
case ONE_AND_ZEROS_PADDING:
|
||||
unsigned int s;
|
||||
s = m_cipher.MandatoryBlockSize();
|
||||
assert(s > 1);
|
||||
space = HelpCreatePutSpace(*AttachedTransformation(), NULL_CHANNEL, s, m_optimalBufferSize);
|
||||
if (m_cipher.IsForwardTransformation())
|
||||
{
|
||||
assert(length < s);
|
||||
memcpy(space, inString, length);
|
||||
if (m_padding == PKCS_PADDING)
|
||||
{
|
||||
assert(s < 256);
|
||||
byte pad = s-length;
|
||||
memset(space+length, pad, s-length);
|
||||
}
|
||||
else
|
||||
{
|
||||
space[length] = 1;
|
||||
memset(space+length+1, 0, s-length-1);
|
||||
}
|
||||
m_cipher.ProcessData(space, space, s);
|
||||
AttachedTransformation()->Put(space, s);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (length != s)
|
||||
throw InvalidCiphertext("StreamTransformationFilter: ciphertext length is not a multiple of block size");
|
||||
m_cipher.ProcessData(space, inString, s);
|
||||
if (m_padding == PKCS_PADDING)
|
||||
{
|
||||
byte pad = space[s-1];
|
||||
if (pad < 1 || pad > s || std::find_if(space+s-pad, space+s, std::bind2nd(std::not_equal_to<byte>(), pad)) != space+s)
|
||||
throw InvalidCiphertext("StreamTransformationFilter: invalid PKCS #7 block padding found");
|
||||
length = s-pad;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (length > 1 && space[length-1] == '\0')
|
||||
--length;
|
||||
if (space[--length] != '\1')
|
||||
throw InvalidCiphertext("StreamTransformationFilter: invalid ones-and-zeros padding found");
|
||||
}
|
||||
AttachedTransformation()->Put(space, length);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
|
||||
void HashFilter::IsolatedInitialize(const NameValuePairs ¶meters)
|
||||
{
|
||||
m_putMessage = parameters.GetValueWithDefault(Name::PutMessage(), false);
|
||||
m_hashModule.Restart();
|
||||
}
|
||||
|
||||
unsigned int HashFilter::Put2(const byte *inString, unsigned int length, int messageEnd, bool blocking)
|
||||
{
|
||||
FILTER_BEGIN;
|
||||
m_hashModule.Update(inString, length);
|
||||
if (m_putMessage)
|
||||
FILTER_OUTPUT(1, inString, length, 0);
|
||||
if (messageEnd)
|
||||
{
|
||||
{
|
||||
unsigned int size, digestSize = m_hashModule.DigestSize();
|
||||
m_space = HelpCreatePutSpace(*AttachedTransformation(), NULL_CHANNEL, digestSize, digestSize, size = digestSize);
|
||||
m_hashModule.Final(m_space);
|
||||
}
|
||||
FILTER_OUTPUT(2, m_space, m_hashModule.DigestSize(), messageEnd);
|
||||
}
|
||||
FILTER_END_NO_MESSAGE_END;
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
|
||||
HashVerificationFilter::HashVerificationFilter(HashTransformation &hm, BufferedTransformation *attachment, word32 flags)
|
||||
: FilterWithBufferedInput(attachment)
|
||||
, m_hashModule(hm)
|
||||
{
|
||||
IsolatedInitialize(MakeParameters(Name::HashVerificationFilterFlags(), flags));
|
||||
}
|
||||
|
||||
void HashVerificationFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, unsigned int &firstSize, unsigned int &blockSize, unsigned int &lastSize)
|
||||
{
|
||||
m_flags = parameters.GetValueWithDefault(Name::HashVerificationFilterFlags(), (word32)DEFAULT_FLAGS);
|
||||
m_hashModule.Restart();
|
||||
unsigned int size = m_hashModule.DigestSize();
|
||||
m_verified = false;
|
||||
firstSize = m_flags & HASH_AT_BEGIN ? size : 0;
|
||||
blockSize = 1;
|
||||
lastSize = m_flags & HASH_AT_BEGIN ? 0 : size;
|
||||
}
|
||||
|
||||
void HashVerificationFilter::FirstPut(const byte *inString)
|
||||
{
|
||||
if (m_flags & HASH_AT_BEGIN)
|
||||
{
|
||||
m_expectedHash.New(m_hashModule.DigestSize());
|
||||
memcpy(m_expectedHash, inString, m_expectedHash.size());
|
||||
if (m_flags & PUT_HASH)
|
||||
AttachedTransformation()->Put(inString, m_expectedHash.size());
|
||||
}
|
||||
}
|
||||
|
||||
void HashVerificationFilter::NextPutMultiple(const byte *inString, unsigned int length)
|
||||
{
|
||||
m_hashModule.Update(inString, length);
|
||||
if (m_flags & PUT_MESSAGE)
|
||||
AttachedTransformation()->Put(inString, length);
|
||||
}
|
||||
|
||||
void HashVerificationFilter::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::IsolatedInitialize(const NameValuePairs ¶meters)
|
||||
{
|
||||
m_putMessage = parameters.GetValueWithDefault(Name::PutMessage(), false);
|
||||
m_messageAccumulator.reset(m_signer.NewSignatureAccumulator());
|
||||
}
|
||||
|
||||
unsigned int SignerFilter::Put2(const byte *inString, unsigned int length, int messageEnd, bool blocking)
|
||||
{
|
||||
FILTER_BEGIN;
|
||||
m_messageAccumulator->Update(inString, length);
|
||||
if (m_putMessage)
|
||||
FILTER_OUTPUT(1, inString, length, 0);
|
||||
if (messageEnd)
|
||||
{
|
||||
m_buf.New(m_signer.SignatureLength());
|
||||
m_signer.Sign(m_rng, m_messageAccumulator.release(), m_buf);
|
||||
FILTER_OUTPUT(2, m_buf, m_buf.size(), messageEnd);
|
||||
m_messageAccumulator.reset(m_signer.NewSignatureAccumulator());
|
||||
}
|
||||
FILTER_END_NO_MESSAGE_END;
|
||||
}
|
||||
|
||||
SignatureVerificationFilter::SignatureVerificationFilter(const PK_Verifier &verifier, BufferedTransformation *attachment, word32 flags)
|
||||
: FilterWithBufferedInput(attachment)
|
||||
, m_verifier(verifier)
|
||||
{
|
||||
IsolatedInitialize(MakeParameters(Name::SignatureVerificationFilterFlags(), flags));
|
||||
}
|
||||
|
||||
void SignatureVerificationFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, unsigned int &firstSize, unsigned int &blockSize, unsigned int &lastSize)
|
||||
{
|
||||
m_flags = parameters.GetValueWithDefault(Name::SignatureVerificationFilterFlags(), (word32)DEFAULT_FLAGS);
|
||||
m_messageAccumulator.reset(m_verifier.NewVerificationAccumulator());
|
||||
unsigned int size = m_verifier.SignatureLength();
|
||||
assert(size != 0); // TODO: handle recoverable signature scheme
|
||||
m_verified = false;
|
||||
firstSize = m_flags & SIGNATURE_AT_BEGIN ? size : 0;
|
||||
blockSize = 1;
|
||||
lastSize = m_flags & SIGNATURE_AT_BEGIN ? 0 : size;
|
||||
}
|
||||
|
||||
void SignatureVerificationFilter::FirstPut(const byte *inString)
|
||||
{
|
||||
if (m_flags & SIGNATURE_AT_BEGIN)
|
||||
{
|
||||
if (m_verifier.SignatureUpfront())
|
||||
m_verifier.InputSignature(*m_messageAccumulator, inString, m_verifier.SignatureLength());
|
||||
else
|
||||
{
|
||||
m_signature.New(m_verifier.SignatureLength());
|
||||
memcpy(m_signature, inString, m_signature.size());
|
||||
}
|
||||
|
||||
if (m_flags & PUT_SIGNATURE)
|
||||
AttachedTransformation()->Put(inString, m_signature.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(!m_verifier.SignatureUpfront());
|
||||
}
|
||||
}
|
||||
|
||||
void SignatureVerificationFilter::NextPutMultiple(const byte *inString, unsigned int length)
|
||||
{
|
||||
m_messageAccumulator->Update(inString, length);
|
||||
if (m_flags & PUT_MESSAGE)
|
||||
AttachedTransformation()->Put(inString, length);
|
||||
}
|
||||
|
||||
void SignatureVerificationFilter::LastPut(const byte *inString, unsigned int length)
|
||||
{
|
||||
if (m_flags & SIGNATURE_AT_BEGIN)
|
||||
{
|
||||
assert(length == 0);
|
||||
m_verifier.InputSignature(*m_messageAccumulator, m_signature, m_signature.size());
|
||||
m_verified = m_verifier.VerifyAndRestart(*m_messageAccumulator);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_verifier.InputSignature(*m_messageAccumulator, inString, length);
|
||||
m_verified = m_verifier.VerifyAndRestart(*m_messageAccumulator);
|
||||
if (m_flags & PUT_SIGNATURE)
|
||||
AttachedTransformation()->Put(inString, length);
|
||||
}
|
||||
|
||||
if (m_flags & PUT_RESULT)
|
||||
AttachedTransformation()->Put(m_verified);
|
||||
|
||||
if ((m_flags & THROW_EXCEPTION) && !m_verified)
|
||||
throw SignatureVerificationFailed();
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
|
||||
unsigned int Source::PumpAll2(bool blocking)
|
||||
{
|
||||
// TODO: switch length type
|
||||
unsigned long i = UINT_MAX;
|
||||
RETURN_IF_NONZERO(Pump2(i, blocking));
|
||||
unsigned int j = UINT_MAX;
|
||||
return PumpMessages2(j, blocking);
|
||||
}
|
||||
|
||||
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 std::string &channel) const
|
||||
{
|
||||
if (m_messageEnd || count == 0)
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
CopyTo(target, ULONG_MAX, channel);
|
||||
if (GetAutoSignalPropagation())
|
||||
target.ChannelMessageEnd(channel, GetAutoSignalPropagation()-1);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
void StringStore::StoreInitialize(const NameValuePairs ¶meters)
|
||||
{
|
||||
ConstByteArrayParameter array;
|
||||
if (!parameters.GetValue(Name::InputBuffer(), array))
|
||||
throw InvalidArgument("StringStore: missing InputBuffer argument");
|
||||
m_store = array.begin();
|
||||
m_length = array.size();
|
||||
m_count = 0;
|
||||
}
|
||||
|
||||
unsigned int StringStore::TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel, bool blocking)
|
||||
{
|
||||
unsigned long position = 0;
|
||||
unsigned int blockedBytes = CopyRangeTo2(target, position, transferBytes, channel, blocking);
|
||||
m_count += position;
|
||||
transferBytes = position;
|
||||
return blockedBytes;
|
||||
}
|
||||
|
||||
unsigned int StringStore::CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end, const std::string &channel, bool blocking) const
|
||||
{
|
||||
unsigned int i = (unsigned int)STDMIN((unsigned long)m_count+begin, (unsigned long)m_length);
|
||||
unsigned int len = (unsigned int)STDMIN((unsigned long)m_length-i, end-begin);
|
||||
unsigned int blockedBytes = target.ChannelPut2(channel, m_store+i, len, 0, blocking);
|
||||
if (!blockedBytes)
|
||||
begin += len;
|
||||
return blockedBytes;
|
||||
}
|
||||
|
||||
unsigned int RandomNumberStore::TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel, bool blocking)
|
||||
{
|
||||
if (!blocking)
|
||||
throw NotImplemented("RandomNumberStore: nonblocking transfer is not implemented by this object");
|
||||
|
||||
unsigned long transferMax = transferBytes;
|
||||
for (transferBytes = 0; transferBytes<transferMax && m_count < m_length; ++transferBytes, ++m_count)
|
||||
target.ChannelPut(channel, m_rng.GenerateByte());
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int NullStore::CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end, const std::string &channel, bool blocking) const
|
||||
{
|
||||
static const byte nullBytes[128] = {0};
|
||||
while (begin < end)
|
||||
{
|
||||
unsigned int len = STDMIN(end-begin, 128UL);
|
||||
unsigned int blockedBytes = target.ChannelPut2(channel, nullBytes, len, 0, blocking);
|
||||
if (blockedBytes)
|
||||
return blockedBytes;
|
||||
begin += len;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int NullStore::TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel, bool blocking)
|
||||
{
|
||||
unsigned long begin = 0;
|
||||
unsigned int blockedBytes = NullStore::CopyRangeTo2(target, begin, transferBytes, channel, blocking);
|
||||
transferBytes = begin;
|
||||
m_size -= begin;
|
||||
return blockedBytes;
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -0,0 +1,688 @@
|
||||
#ifndef CRYPTOPP_FILTERS_H
|
||||
#define CRYPTOPP_FILTERS_H
|
||||
|
||||
#include "simple.h"
|
||||
#include "secblock.h"
|
||||
#include "misc.h"
|
||||
#include "smartptr.h"
|
||||
#include "queue.h"
|
||||
#include "algparam.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
/// provides an implementation of BufferedTransformation's attachment interface
|
||||
class Filter : public BufferedTransformation, public NotCopyable
|
||||
{
|
||||
public:
|
||||
Filter(BufferedTransformation *attachment);
|
||||
|
||||
bool Attachable() {return true;}
|
||||
BufferedTransformation *AttachedTransformation();
|
||||
const BufferedTransformation *AttachedTransformation() const;
|
||||
void Detach(BufferedTransformation *newAttachment = NULL);
|
||||
|
||||
unsigned int TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel=NULL_CHANNEL, bool blocking=true);
|
||||
unsigned int CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end=ULONG_MAX, const std::string &channel=NULL_CHANNEL, bool blocking=true) const;
|
||||
|
||||
void Initialize(const NameValuePairs ¶meters=g_nullNameValuePairs, int propagation=-1);
|
||||
bool Flush(bool hardFlush, int propagation=-1, bool blocking=true);
|
||||
bool MessageSeriesEnd(int propagation=-1, bool blocking=true);
|
||||
|
||||
protected:
|
||||
virtual void NotifyAttachmentChange() {}
|
||||
virtual BufferedTransformation * NewDefaultAttachment() const;
|
||||
void Insert(Filter *nextFilter); // insert filter after this one
|
||||
|
||||
virtual bool ShouldPropagateMessageEnd() const {return true;}
|
||||
virtual bool ShouldPropagateMessageSeriesEnd() const {return true;}
|
||||
|
||||
void PropagateInitialize(const NameValuePairs ¶meters, int propagation, const std::string &channel=NULL_CHANNEL);
|
||||
|
||||
unsigned int Output(int outputSite, const byte *inString, unsigned int length, int messageEnd, bool blocking, const std::string &channel=NULL_CHANNEL);
|
||||
bool OutputMessageEnd(int outputSite, int propagation, bool blocking, const std::string &channel=NULL_CHANNEL);
|
||||
bool OutputFlush(int outputSite, bool hardFlush, int propagation, bool blocking, const std::string &channel=NULL_CHANNEL);
|
||||
bool OutputMessageSeriesEnd(int outputSite, int propagation, bool blocking, const std::string &channel=NULL_CHANNEL);
|
||||
|
||||
private:
|
||||
member_ptr<BufferedTransformation> m_attachment;
|
||||
|
||||
protected:
|
||||
unsigned int m_inputPosition;
|
||||
int m_continueAt;
|
||||
};
|
||||
|
||||
struct FilterPutSpaceHelper
|
||||
{
|
||||
// desiredSize is how much to ask target, bufferSize is how much to allocate in m_tempSpace
|
||||
byte *HelpCreatePutSpace(BufferedTransformation &target, const std::string &channel, unsigned int minSize, unsigned int desiredSize, unsigned int &bufferSize)
|
||||
{
|
||||
assert(desiredSize >= minSize && bufferSize >= minSize);
|
||||
if (m_tempSpace.size() < minSize)
|
||||
{
|
||||
byte *result = target.ChannelCreatePutSpace(channel, desiredSize);
|
||||
if (desiredSize >= minSize)
|
||||
{
|
||||
bufferSize = desiredSize;
|
||||
return result;
|
||||
}
|
||||
m_tempSpace.New(bufferSize);
|
||||
}
|
||||
|
||||
bufferSize = m_tempSpace.size();
|
||||
return m_tempSpace.begin();
|
||||
}
|
||||
byte *HelpCreatePutSpace(BufferedTransformation &target, const std::string &channel, unsigned int minSize)
|
||||
{return HelpCreatePutSpace(target, channel, minSize, minSize, minSize);}
|
||||
byte *HelpCreatePutSpace(BufferedTransformation &target, const std::string &channel, unsigned int minSize, unsigned int bufferSize)
|
||||
{return HelpCreatePutSpace(target, channel, minSize, minSize, bufferSize);}
|
||||
SecByteBlock m_tempSpace;
|
||||
};
|
||||
|
||||
//! measure how many byte and messages pass through, also serves as valve
|
||||
class MeterFilter : public Bufferless<Filter>
|
||||
{
|
||||
public:
|
||||
MeterFilter(BufferedTransformation *attachment=NULL, bool transparent=true)
|
||||
: Bufferless<Filter>(attachment), m_transparent(transparent) {ResetMeter();}
|
||||
|
||||
void SetTransparent(bool transparent) {m_transparent = transparent;}
|
||||
void ResetMeter() {m_currentMessageBytes = m_totalBytes = m_currentSeriesMessages = m_totalMessages = m_totalMessageSeries = 0;}
|
||||
|
||||
unsigned long GetCurrentMessageBytes() const {return m_currentMessageBytes;}
|
||||
unsigned long GetTotalBytes() {return m_totalBytes;}
|
||||
unsigned int GetCurrentSeriesMessages() {return m_currentSeriesMessages;}
|
||||
unsigned int GetTotalMessages() {return m_totalMessages;}
|
||||
unsigned int GetTotalMessageSeries() {return m_totalMessageSeries;}
|
||||
|
||||
unsigned int Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking);
|
||||
bool IsolatedMessageSeriesEnd(bool blocking);
|
||||
|
||||
private:
|
||||
bool ShouldPropagateMessageEnd() const {return m_transparent;}
|
||||
bool ShouldPropagateMessageSeriesEnd() const {return m_transparent;}
|
||||
|
||||
bool m_transparent;
|
||||
unsigned long m_currentMessageBytes, m_totalBytes;
|
||||
unsigned int m_currentSeriesMessages, m_totalMessages, m_totalMessageSeries;
|
||||
};
|
||||
|
||||
//! .
|
||||
class TransparentFilter : public MeterFilter
|
||||
{
|
||||
public:
|
||||
TransparentFilter(BufferedTransformation *attachment=NULL) : MeterFilter(attachment, true) {}
|
||||
};
|
||||
|
||||
//! .
|
||||
class OpaqueFilter : public MeterFilter
|
||||
{
|
||||
public:
|
||||
OpaqueFilter(BufferedTransformation *attachment=NULL) : MeterFilter(attachment, false) {}
|
||||
};
|
||||
|
||||
/*! 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:
|
||||
FilterWithBufferedInput(BufferedTransformation *attachment);
|
||||
//! firstSize and lastSize may be 0, blockSize must be at least 1
|
||||
FilterWithBufferedInput(unsigned int firstSize, unsigned int blockSize, unsigned int lastSize, BufferedTransformation *attachment);
|
||||
|
||||
void IsolatedInitialize(const NameValuePairs ¶meters);
|
||||
unsigned int Put2(const byte *inString, unsigned int length, int messageEnd, bool blocking)
|
||||
{
|
||||
return PutMaybeModifiable(const_cast<byte *>(inString), length, messageEnd, blocking, false);
|
||||
}
|
||||
unsigned int PutModifiable2(byte *inString, unsigned int length, int messageEnd, bool blocking)
|
||||
{
|
||||
return PutMaybeModifiable(inString, length, messageEnd, blocking, true);
|
||||
}
|
||||
/*! calls ForceNextPut() if hardFlush is true */
|
||||
bool IsolatedFlush(bool hardFlush, bool blocking);
|
||||
|
||||
/*! 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;}
|
||||
|
||||
virtual void InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, unsigned int &firstSize, unsigned int &blockSize, unsigned int &lastSize)
|
||||
{InitializeDerived(parameters);}
|
||||
virtual void InitializeDerived(const NameValuePairs ¶meters) {}
|
||||
// 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
|
||||
virtual void NextPutSingle(const byte *inString) {assert(false);}
|
||||
// Same as NextPut() except length can be a multiple of blockSize
|
||||
// Either NextPut() or NextPutMultiple() must be overriden
|
||||
virtual void NextPutMultiple(const byte *inString, unsigned int length);
|
||||
// Same as NextPutMultiple(), but inString can be modified
|
||||
virtual void NextPutModifiable(byte *inString, unsigned int length)
|
||||
{NextPutMultiple(inString, length);}
|
||||
// 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;
|
||||
virtual void FlushDerived() {}
|
||||
|
||||
private:
|
||||
unsigned int PutMaybeModifiable(byte *begin, unsigned int length, int messageEnd, bool blocking, bool modifiable);
|
||||
void NextPutMaybeModifiable(byte *inString, unsigned int length, bool modifiable)
|
||||
{
|
||||
if (modifiable) NextPutModifiable(inString, length);
|
||||
else NextPutMultiple(inString, length);
|
||||
}
|
||||
|
||||
// This function should no longer be used, put this here to cause a compiler error
|
||||
// if someone tries to override NextPut().
|
||||
virtual int NextPut(const byte *inString, unsigned int length) {assert(false); return 0;}
|
||||
|
||||
class BlockQueue
|
||||
{
|
||||
public:
|
||||
void ResetQueue(unsigned int blockSize, unsigned int maxBlocks);
|
||||
byte *GetBlock();
|
||||
byte *GetContigousBlocks(unsigned int &numberOfBytes);
|
||||
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) {}
|
||||
unsigned int Put2(const byte *inString, unsigned int length, int messageEnd, bool blocking)
|
||||
{
|
||||
if (!blocking)
|
||||
throw BlockingInputOnly("FilterWithInputQueue");
|
||||
|
||||
m_inQueue.Put(inString, length);
|
||||
if (messageEnd)
|
||||
{
|
||||
IsolatedMessageEnd(blocking);
|
||||
Output(0, NULL, 0, messageEnd, blocking);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool IsolatedMessageEnd(bool blocking) =0;
|
||||
void IsolatedInitialize(const NameValuePairs ¶meters) {m_inQueue.Clear();}
|
||||
|
||||
ByteQueue m_inQueue;
|
||||
};
|
||||
|
||||
//! Filter Wrapper for StreamTransformation
|
||||
class StreamTransformationFilter : public FilterWithBufferedInput, private FilterPutSpaceHelper
|
||||
{
|
||||
public:
|
||||
enum BlockPaddingScheme {NO_PADDING, ZEROS_PADDING, PKCS_PADDING, ONE_AND_ZEROS_PADDING, DEFAULT_PADDING};
|
||||
/*! DEFAULT_PADDING means PKCS_PADDING if c.MandatoryBlockSize() > 1 && c.MinLastBlockSize() == 0 (e.g. ECB or CBC mode),
|
||||
otherwise NO_PADDING (OFB, CFB, CTR, CBC-CTS modes) */
|
||||
StreamTransformationFilter(StreamTransformation &c, BufferedTransformation *attachment = NULL, BlockPaddingScheme padding = DEFAULT_PADDING);
|
||||
|
||||
void FirstPut(const byte *inString);
|
||||
void NextPutMultiple(const byte *inString, unsigned int length);
|
||||
void NextPutModifiable(byte *inString, unsigned int length);
|
||||
void LastPut(const byte *inString, unsigned int length);
|
||||
// byte * CreatePutSpace(unsigned int &size);
|
||||
|
||||
protected:
|
||||
static unsigned int LastBlockSize(StreamTransformation &c, BlockPaddingScheme padding);
|
||||
|
||||
StreamTransformation &m_cipher;
|
||||
BlockPaddingScheme m_padding;
|
||||
unsigned int m_optimalBufferSize;
|
||||
};
|
||||
|
||||
#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
|
||||
typedef StreamTransformationFilter StreamCipherFilter;
|
||||
#endif
|
||||
|
||||
//! Filter Wrapper for HashTransformation
|
||||
class HashFilter : public Bufferless<Filter>, private FilterPutSpaceHelper
|
||||
{
|
||||
public:
|
||||
HashFilter(HashTransformation &hm, BufferedTransformation *attachment = NULL, bool putMessage=false)
|
||||
: Bufferless<Filter>(attachment), m_hashModule(hm), m_putMessage(putMessage) {}
|
||||
|
||||
void IsolatedInitialize(const NameValuePairs ¶meters);
|
||||
unsigned int Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking);
|
||||
|
||||
byte * CreatePutSpace(unsigned int &size) {return m_hashModule.CreateUpdateSpace(size);}
|
||||
|
||||
private:
|
||||
HashTransformation &m_hashModule;
|
||||
bool m_putMessage;
|
||||
byte *m_space;
|
||||
};
|
||||
|
||||
//! Filter Wrapper for HashTransformation
|
||||
class HashVerificationFilter : public FilterWithBufferedInput
|
||||
{
|
||||
public:
|
||||
class HashVerificationFailed : public Exception
|
||||
{
|
||||
public:
|
||||
HashVerificationFailed()
|
||||
: Exception(DATA_INTEGRITY_CHECK_FAILED, "HashVerifier: message hash not valid") {}
|
||||
};
|
||||
|
||||
enum Flags {HASH_AT_BEGIN=1, PUT_MESSAGE=2, PUT_HASH=4, PUT_RESULT=8, THROW_EXCEPTION=16, DEFAULT_FLAGS = HASH_AT_BEGIN | PUT_RESULT};
|
||||
HashVerificationFilter(HashTransformation &hm, BufferedTransformation *attachment = NULL, word32 flags = DEFAULT_FLAGS);
|
||||
|
||||
bool GetLastResult() const {return m_verified;}
|
||||
|
||||
protected:
|
||||
void InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, unsigned int &firstSize, unsigned int &blockSize, unsigned int &lastSize);
|
||||
void FirstPut(const byte *inString);
|
||||
void NextPutMultiple(const byte *inString, unsigned int length);
|
||||
void LastPut(const byte *inString, unsigned int length);
|
||||
|
||||
private:
|
||||
static inline unsigned int FirstSize(word32 flags, HashTransformation &hm) {return flags & HASH_AT_BEGIN ? hm.DigestSize() : 0;}
|
||||
static inline unsigned int LastSize(word32 flags, HashTransformation &hm) {return flags & HASH_AT_BEGIN ? 0 : hm.DigestSize();}
|
||||
|
||||
HashTransformation &m_hashModule;
|
||||
word32 m_flags;
|
||||
SecByteBlock m_expectedHash;
|
||||
bool m_verified;
|
||||
};
|
||||
|
||||
typedef HashVerificationFilter HashVerifier; // for backwards compatibility
|
||||
|
||||
//! Filter Wrapper for PK_Signer
|
||||
class SignerFilter : public Unflushable<Filter>
|
||||
{
|
||||
public:
|
||||
SignerFilter(RandomNumberGenerator &rng, const PK_Signer &signer, BufferedTransformation *attachment = NULL, bool putMessage=false)
|
||||
: Unflushable<Filter>(attachment), m_rng(rng), m_signer(signer), m_messageAccumulator(signer.NewSignatureAccumulator()), m_putMessage(putMessage) {}
|
||||
|
||||
void IsolatedInitialize(const NameValuePairs ¶meters);
|
||||
unsigned int Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking);
|
||||
|
||||
private:
|
||||
RandomNumberGenerator &m_rng;
|
||||
const PK_Signer &m_signer;
|
||||
member_ptr<PK_MessageAccumulator> m_messageAccumulator;
|
||||
bool m_putMessage;
|
||||
SecByteBlock m_buf;
|
||||
};
|
||||
|
||||
//! Filter Wrapper for PK_Verifier
|
||||
class SignatureVerificationFilter : public FilterWithBufferedInput
|
||||
{
|
||||
public:
|
||||
class SignatureVerificationFailed : public Exception
|
||||
{
|
||||
public:
|
||||
SignatureVerificationFailed()
|
||||
: Exception(DATA_INTEGRITY_CHECK_FAILED, "VerifierFilter: digital signature not valid") {}
|
||||
};
|
||||
|
||||
enum Flags {SIGNATURE_AT_BEGIN=1, PUT_MESSAGE=2, PUT_SIGNATURE=4, PUT_RESULT=8, THROW_EXCEPTION=16, DEFAULT_FLAGS = SIGNATURE_AT_BEGIN | PUT_RESULT};
|
||||
SignatureVerificationFilter(const PK_Verifier &verifier, BufferedTransformation *attachment = NULL, word32 flags = DEFAULT_FLAGS);
|
||||
|
||||
bool GetLastResult() const {return m_verified;}
|
||||
|
||||
protected:
|
||||
void InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, unsigned int &firstSize, unsigned int &blockSize, unsigned int &lastSize);
|
||||
void FirstPut(const byte *inString);
|
||||
void NextPutMultiple(const byte *inString, unsigned int length);
|
||||
void LastPut(const byte *inString, unsigned int length);
|
||||
|
||||
private:
|
||||
const PK_Verifier &m_verifier;
|
||||
member_ptr<PK_MessageAccumulator> m_messageAccumulator;
|
||||
word32 m_flags;
|
||||
SecByteBlock m_signature;
|
||||
bool m_verified;
|
||||
};
|
||||
|
||||
typedef SignatureVerificationFilter VerifierFilter; // for backwards compatibility
|
||||
|
||||
//! Redirect input to another BufferedTransformation without owning it
|
||||
class Redirector : public CustomSignalPropagation<Sink>
|
||||
{
|
||||
public:
|
||||
Redirector() : m_target(NULL), m_passSignal(true) {}
|
||||
Redirector(BufferedTransformation &target, bool passSignal=true) : m_target(&target), m_passSignal(passSignal) {}
|
||||
|
||||
void Redirect(BufferedTransformation &target) {m_target = ⌖}
|
||||
void StopRedirection() {m_target = NULL;}
|
||||
bool GetPassSignal() const {return m_passSignal;}
|
||||
void SetPassSignal(bool passSignal) {m_passSignal = passSignal;}
|
||||
|
||||
unsigned int Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking)
|
||||
{return m_target ? m_target->Put2(begin, length, m_passSignal ? messageEnd : 0, blocking) : 0;}
|
||||
void Initialize(const NameValuePairs ¶meters, int propagation)
|
||||
{ChannelInitialize(NULL_CHANNEL, parameters, propagation);}
|
||||
bool Flush(bool hardFlush, int propagation=-1, bool blocking=true)
|
||||
{return m_target && m_passSignal ? m_target->Flush(hardFlush, propagation, blocking) : false;}
|
||||
bool MessageSeriesEnd(int propagation=-1, bool blocking=true)
|
||||
{return m_target && m_passSignal ? m_target->MessageSeriesEnd(propagation, blocking) : false;}
|
||||
|
||||
void ChannelInitialize(const std::string &channel, const NameValuePairs ¶meters=g_nullNameValuePairs, int propagation=-1);
|
||||
unsigned int ChannelPut2(const std::string &channel, const byte *begin, unsigned int length, int messageEnd, bool blocking)
|
||||
{return m_target ? m_target->ChannelPut2(channel, begin, length, m_passSignal ? messageEnd : 0, blocking) : 0;}
|
||||
unsigned int ChannelPutModifiable2(const std::string &channel, byte *begin, unsigned int length, int messageEnd, bool blocking)
|
||||
{return m_target ? m_target->ChannelPutModifiable2(channel, begin, length, m_passSignal ? messageEnd : 0, blocking) : 0;}
|
||||
bool ChannelFlush(const std::string &channel, bool completeFlush, int propagation=-1, bool blocking=true)
|
||||
{return m_target && m_passSignal ? m_target->ChannelFlush(channel, completeFlush, propagation, blocking) : false;}
|
||||
bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true)
|
||||
{return m_target && m_passSignal ? m_target->ChannelMessageSeriesEnd(channel, propagation, blocking) : false;}
|
||||
|
||||
private:
|
||||
BufferedTransformation *m_target;
|
||||
bool m_passSignal;
|
||||
};
|
||||
|
||||
// Used By ProxyFilter
|
||||
class OutputProxy : public CustomSignalPropagation<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;}
|
||||
|
||||
unsigned int Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking)
|
||||
{return m_owner.AttachedTransformation()->Put2(begin, length, m_passSignal ? messageEnd : 0, blocking);}
|
||||
unsigned int PutModifiable2(byte *begin, unsigned int length, int messageEnd, bool blocking)
|
||||
{return m_owner.AttachedTransformation()->PutModifiable2(begin, length, m_passSignal ? messageEnd : 0, blocking);}
|
||||
void Initialize(const NameValuePairs ¶meters=g_nullNameValuePairs, int propagation=-1)
|
||||
{if (m_passSignal) m_owner.AttachedTransformation()->Initialize(parameters, propagation);}
|
||||
bool Flush(bool hardFlush, int propagation=-1, bool blocking=true)
|
||||
{return m_passSignal ? m_owner.AttachedTransformation()->Flush(hardFlush, propagation, blocking) : false;}
|
||||
bool MessageSeriesEnd(int propagation=-1, bool blocking=true)
|
||||
{return m_passSignal ? m_owner.AttachedTransformation()->MessageSeriesEnd(propagation, blocking) : false;}
|
||||
|
||||
unsigned int ChannelPut2(const std::string &channel, const byte *begin, unsigned int length, int messageEnd, bool blocking)
|
||||
{return m_owner.AttachedTransformation()->ChannelPut2(channel, begin, length, m_passSignal ? messageEnd : 0, blocking);}
|
||||
unsigned int ChannelPutModifiable2(const std::string &channel, byte *begin, unsigned int length, int messageEnd, bool blocking)
|
||||
{return m_owner.AttachedTransformation()->ChannelPutModifiable2(channel, begin, length, m_passSignal ? messageEnd : 0, blocking);}
|
||||
void ChannelInitialize(const std::string &channel, const NameValuePairs ¶meters, int propagation=-1)
|
||||
{if (m_passSignal) m_owner.AttachedTransformation()->ChannelInitialize(channel, parameters, propagation);}
|
||||
bool ChannelFlush(const std::string &channel, bool completeFlush, int propagation=-1, bool blocking=true)
|
||||
{return m_passSignal ? m_owner.AttachedTransformation()->ChannelFlush(channel, completeFlush, propagation, blocking) : false;}
|
||||
bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true)
|
||||
{return m_passSignal ? m_owner.AttachedTransformation()->ChannelMessageSeriesEnd(channel, propagation, blocking) : false;}
|
||||
|
||||
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(BufferedTransformation *filter, unsigned int firstSize, unsigned int lastSize, BufferedTransformation *attachment);
|
||||
|
||||
bool IsolatedFlush(bool hardFlush, bool blocking);
|
||||
|
||||
void SetFilter(Filter *filter);
|
||||
void NextPutMultiple(const byte *s, unsigned int len);
|
||||
|
||||
protected:
|
||||
member_ptr<BufferedTransformation> m_filter;
|
||||
};
|
||||
|
||||
//! simple proxy filter that doesn't modify the underlying filter's input or output
|
||||
class SimpleProxyFilter : public ProxyFilter
|
||||
{
|
||||
public:
|
||||
SimpleProxyFilter(BufferedTransformation *filter, BufferedTransformation *attachment)
|
||||
: ProxyFilter(filter, 0, 0, attachment) {}
|
||||
|
||||
void FirstPut(const byte *) {}
|
||||
void LastPut(const byte *, unsigned int) {m_filter->MessageEnd();}
|
||||
};
|
||||
|
||||
//! proxy for the filter created by PK_Encryptor::CreateEncryptionFilter
|
||||
/*! This class is here just to provide symmetry with VerifierFilter. */
|
||||
class PK_EncryptorFilter : public SimpleProxyFilter
|
||||
{
|
||||
public:
|
||||
PK_EncryptorFilter(RandomNumberGenerator &rng, const PK_Encryptor &encryptor, BufferedTransformation *attachment = NULL)
|
||||
: SimpleProxyFilter(encryptor.CreateEncryptionFilter(rng), attachment) {}
|
||||
};
|
||||
|
||||
//! proxy for the filter created by PK_Decryptor::CreateDecryptionFilter
|
||||
/*! This class is here just to provide symmetry with SignerFilter. */
|
||||
class PK_DecryptorFilter : public SimpleProxyFilter
|
||||
{
|
||||
public:
|
||||
PK_DecryptorFilter(RandomNumberGenerator &rng, const PK_Decryptor &decryptor, BufferedTransformation *attachment = NULL)
|
||||
: SimpleProxyFilter(decryptor.CreateDecryptionFilter(rng), attachment) {}
|
||||
};
|
||||
|
||||
//! Append input to a string object
|
||||
template <class T>
|
||||
class StringSinkTemplate : public Bufferless<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 IsolatedInitialize(const NameValuePairs ¶meters)
|
||||
{if (!parameters.GetValue("OutputStringPointer", m_output)) throw InvalidArgument("StringSink: OutputStringPointer not specified");}
|
||||
|
||||
unsigned int Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking)
|
||||
{
|
||||
if (length > 0)
|
||||
{
|
||||
typename T::size_type size = m_output->size();
|
||||
if (length < size && size + length > m_output->capacity())
|
||||
m_output->reserve(2*size);
|
||||
m_output->append((const char_type *)begin, (const char_type *)begin+length);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
T *m_output;
|
||||
};
|
||||
|
||||
//! Append input to an std::string
|
||||
typedef StringSinkTemplate<std::string> StringSink;
|
||||
|
||||
//! Copy input to a memory buffer
|
||||
class ArraySink : public Bufferless<Sink>
|
||||
{
|
||||
public:
|
||||
ArraySink(const NameValuePairs ¶meters = g_nullNameValuePairs) {IsolatedInitialize(parameters);}
|
||||
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 IsolatedInitialize(const NameValuePairs ¶meters);
|
||||
byte * CreatePutSpace(unsigned int &size);
|
||||
unsigned int Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking);
|
||||
|
||||
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) {}
|
||||
|
||||
unsigned int Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking);
|
||||
byte * CreatePutSpace(unsigned int &size) {return BufferedTransformation::CreatePutSpace(size);}
|
||||
};
|
||||
|
||||
//! .
|
||||
class StringStore : public Store
|
||||
{
|
||||
public:
|
||||
StringStore(const char *string = NULL)
|
||||
{StoreInitialize(MakeParameters("InputBuffer", ConstByteArrayParameter(string)));}
|
||||
StringStore(const byte *string, unsigned int length)
|
||||
{StoreInitialize(MakeParameters("InputBuffer", ConstByteArrayParameter(string, length)));}
|
||||
template <class T> StringStore(const T &string)
|
||||
{StoreInitialize(MakeParameters("InputBuffer", ConstByteArrayParameter(string)));}
|
||||
|
||||
unsigned int TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel=NULL_CHANNEL, bool blocking=true);
|
||||
unsigned int CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end=ULONG_MAX, const std::string &channel=NULL_CHANNEL, bool blocking=true) const;
|
||||
|
||||
private:
|
||||
void StoreInitialize(const NameValuePairs ¶meters);
|
||||
|
||||
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) {}
|
||||
|
||||
bool AnyRetrievable() const {return MaxRetrievable() != 0;}
|
||||
unsigned long MaxRetrievable() const {return m_length-m_count;}
|
||||
|
||||
unsigned int TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel=NULL_CHANNEL, bool blocking=true);
|
||||
unsigned int CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end=ULONG_MAX, const std::string &channel=NULL_CHANNEL, bool blocking=true) const
|
||||
{
|
||||
throw NotImplemented("RandomNumberStore: CopyRangeTo2() is not supported by this store");
|
||||
}
|
||||
|
||||
private:
|
||||
void StoreInitialize(const NameValuePairs ¶meters) {m_count = 0;}
|
||||
|
||||
RandomNumberGenerator &m_rng;
|
||||
const unsigned long m_length;
|
||||
unsigned long m_count;
|
||||
};
|
||||
|
||||
//! .
|
||||
class NullStore : public Store
|
||||
{
|
||||
public:
|
||||
NullStore(unsigned long size = ULONG_MAX) : m_size(size) {}
|
||||
void StoreInitialize(const NameValuePairs ¶meters) {}
|
||||
unsigned long MaxRetrievable() const {return m_size;}
|
||||
unsigned int TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel=NULL_CHANNEL, bool blocking=true);
|
||||
unsigned int CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end=ULONG_MAX, const std::string &channel=NULL_CHANNEL, bool blocking=true) const;
|
||||
|
||||
private:
|
||||
unsigned long m_size;
|
||||
};
|
||||
|
||||
//! A Filter that pumps data into its attachment as input
|
||||
class Source : public InputRejecting<Filter>
|
||||
{
|
||||
public:
|
||||
Source(BufferedTransformation *attachment)
|
||||
: InputRejecting<Filter>(attachment) {}
|
||||
|
||||
unsigned long Pump(unsigned long pumpMax=ULONG_MAX)
|
||||
{Pump2(pumpMax); return pumpMax;}
|
||||
unsigned int PumpMessages(unsigned int count=UINT_MAX)
|
||||
{PumpMessages2(count); return count;}
|
||||
void PumpAll()
|
||||
{PumpAll2();}
|
||||
virtual unsigned int Pump2(unsigned long &byteCount, bool blocking=true) =0;
|
||||
virtual unsigned int PumpMessages2(unsigned int &messageCount, bool blocking=true) =0;
|
||||
virtual unsigned int PumpAll2(bool blocking=true);
|
||||
virtual bool SourceExhausted() const =0;
|
||||
|
||||
protected:
|
||||
void SourceInitialize(bool pumpAll, const NameValuePairs ¶meters)
|
||||
{
|
||||
IsolatedInitialize(parameters);
|
||||
if (pumpAll)
|
||||
PumpAll();
|
||||
}
|
||||
};
|
||||
|
||||
//! Turn a Store into a Source
|
||||
template <class T>
|
||||
class SourceTemplate : public Source
|
||||
{
|
||||
public:
|
||||
SourceTemplate<T>(BufferedTransformation *attachment)
|
||||
: Source(attachment) {}
|
||||
SourceTemplate<T>(BufferedTransformation *attachment, T store)
|
||||
: Source(attachment), m_store(store) {}
|
||||
void IsolatedInitialize(const NameValuePairs ¶meters)
|
||||
{m_store.IsolatedInitialize(parameters);}
|
||||
unsigned int Pump2(unsigned long &byteCount, bool blocking=true)
|
||||
{return m_store.TransferTo2(*AttachedTransformation(), byteCount, NULL_CHANNEL, blocking);}
|
||||
unsigned int PumpMessages2(unsigned int &messageCount, bool blocking=true)
|
||||
{return m_store.TransferMessagesTo2(*AttachedTransformation(), messageCount, NULL_CHANNEL, blocking);}
|
||||
unsigned int PumpAll2(bool blocking=true)
|
||||
{return m_store.TransferAllTo2(*AttachedTransformation(), NULL_CHANNEL, blocking);}
|
||||
bool SourceExhausted() const
|
||||
{return !m_store.AnyRetrievable() && !m_store.AnyMessages();}
|
||||
void SetAutoSignalPropagation(int propagation)
|
||||
{m_store.SetAutoSignalPropagation(propagation);}
|
||||
int GetAutoSignalPropagation() const
|
||||
{return m_store.GetAutoSignalPropagation();}
|
||||
|
||||
protected:
|
||||
T m_store;
|
||||
};
|
||||
|
||||
//! .
|
||||
class StringSource : public SourceTemplate<StringStore>
|
||||
{
|
||||
public:
|
||||
StringSource(BufferedTransformation *attachment = NULL)
|
||||
: SourceTemplate<StringStore>(attachment) {}
|
||||
StringSource(const char *string, bool pumpAll, BufferedTransformation *attachment = NULL)
|
||||
: SourceTemplate<StringStore>(attachment) {SourceInitialize(pumpAll, MakeParameters("InputBuffer", ConstByteArrayParameter(string)));}
|
||||
StringSource(const byte *string, unsigned int length, bool pumpAll, BufferedTransformation *attachment = NULL)
|
||||
: SourceTemplate<StringStore>(attachment) {SourceInitialize(pumpAll, MakeParameters("InputBuffer", ConstByteArrayParameter(string, length)));}
|
||||
|
||||
#ifdef __MWERKS__ // CW60 workaround
|
||||
StringSource(const std::string &string, bool pumpAll, BufferedTransformation *attachment = NULL)
|
||||
#else
|
||||
template <class T> StringSource(const T &string, bool pumpAll, BufferedTransformation *attachment = NULL)
|
||||
#endif
|
||||
: SourceTemplate<StringStore>(attachment) {SourceInitialize(pumpAll, MakeParameters("InputBuffer", ConstByteArrayParameter(string)));}
|
||||
};
|
||||
|
||||
//! .
|
||||
class RandomNumberSource : public SourceTemplate<RandomNumberStore>
|
||||
{
|
||||
public:
|
||||
RandomNumberSource(RandomNumberGenerator &rng, unsigned int length, bool pumpAll, BufferedTransformation *attachment = NULL)
|
||||
: SourceTemplate<RandomNumberStore>(attachment, RandomNumberStore(rng, length)) {if (pumpAll) PumpAll();}
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,79 @@
|
||||
// fips140.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
#include "fips140.h"
|
||||
#include "trdlocal.h" // needs to be included last for cygwin
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
// Define this to 1 to turn on FIPS 140-2 compliance features, including additional tests during
|
||||
// startup, random number generation, and key generation. These tests may affect performance.
|
||||
#ifndef CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2
|
||||
#define CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 0
|
||||
#endif
|
||||
|
||||
#if (CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 && !defined(THREADS_AVAILABLE))
|
||||
#error FIPS 140-2 compliance requires the availability of thread local storage.
|
||||
#endif
|
||||
|
||||
#if (CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 && !defined(OS_RNG_AVAILABLE))
|
||||
#error FIPS 140-2 compliance requires the availability of OS provided RNG.
|
||||
#endif
|
||||
|
||||
PowerUpSelfTestStatus g_powerUpSelfTestStatus = POWER_UP_SELF_TEST_NOT_DONE;
|
||||
|
||||
bool FIPS_140_2_ComplianceEnabled()
|
||||
{
|
||||
return CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2;
|
||||
}
|
||||
|
||||
void SimulatePowerUpSelfTestFailure()
|
||||
{
|
||||
g_powerUpSelfTestStatus = POWER_UP_SELF_TEST_FAILED;
|
||||
}
|
||||
|
||||
PowerUpSelfTestStatus GetPowerUpSelfTestStatus()
|
||||
{
|
||||
return g_powerUpSelfTestStatus;
|
||||
}
|
||||
|
||||
#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2
|
||||
ThreadLocalStorage & AccessPowerUpSelfTestInProgress()
|
||||
{
|
||||
static ThreadLocalStorage selfTestInProgress;
|
||||
return selfTestInProgress;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool PowerUpSelfTestInProgressOnThisThread()
|
||||
{
|
||||
#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2
|
||||
return AccessPowerUpSelfTestInProgress().GetValue() != NULL;
|
||||
#else
|
||||
assert(false); // should not be called
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void SetPowerUpSelfTestInProgressOnThisThread(bool inProgress)
|
||||
{
|
||||
#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2
|
||||
AccessPowerUpSelfTestInProgress().SetValue((void *)inProgress);
|
||||
#endif
|
||||
}
|
||||
|
||||
void EncryptionPairwiseConsistencyTest_FIPS_140_Only(const PK_Encryptor &encryptor, const PK_Decryptor &decryptor)
|
||||
{
|
||||
#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2
|
||||
EncryptionPairwiseConsistencyTest(encryptor, decryptor);
|
||||
#endif
|
||||
}
|
||||
|
||||
void SignaturePairwiseConsistencyTest_FIPS_140_Only(const PK_Signer &signer, const PK_Verifier &verifier)
|
||||
{
|
||||
#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2
|
||||
SignaturePairwiseConsistencyTest(signer, verifier);
|
||||
#endif
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -0,0 +1,47 @@
|
||||
#ifndef CRYPTOPP_FIPS140_H
|
||||
#define CRYPTOPP_FIPS140_H
|
||||
|
||||
/*! \file
|
||||
FIPS 140 related functions and classes.
|
||||
*/
|
||||
|
||||
#include "cryptlib.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
//! exception thrown when a crypto algorithm is used after a self test fails
|
||||
class SelfTestFailure : public Exception
|
||||
{
|
||||
public:
|
||||
explicit SelfTestFailure(const std::string &s) : Exception(OTHER_ERROR, s) {}
|
||||
};
|
||||
|
||||
//! returns whether FIPS 140-2 compliance features were enabled at compile time
|
||||
bool FIPS_140_2_ComplianceEnabled();
|
||||
|
||||
//! enum values representing status of the power-up self test
|
||||
enum PowerUpSelfTestStatus {POWER_UP_SELF_TEST_NOT_DONE, POWER_UP_SELF_TEST_FAILED, POWER_UP_SELF_TEST_PASSED};
|
||||
|
||||
//! perform the power-up self test, and set the self test status
|
||||
void DoPowerUpSelfTest(const char *moduleFilename, const byte *expectedModuleSha1Digest);
|
||||
|
||||
//! set the power-up self test status to POWER_UP_SELF_TEST_FAILED
|
||||
void SimulatePowerUpSelfTestFailure();
|
||||
|
||||
//! return the current power-up self test status
|
||||
PowerUpSelfTestStatus GetPowerUpSelfTestStatus();
|
||||
|
||||
// this is used by Algorithm constructor to allow Algorithm objects to be constructed for the self test
|
||||
bool PowerUpSelfTestInProgressOnThisThread();
|
||||
|
||||
void SetPowerUpSelfTestInProgressOnThisThread(bool inProgress);
|
||||
|
||||
void SignaturePairwiseConsistencyTest(const PK_Signer &signer, const PK_Verifier &verifier);
|
||||
void EncryptionPairwiseConsistencyTest(const PK_Encryptor &encryptor, const PK_Decryptor &decryptor);
|
||||
|
||||
void SignaturePairwiseConsistencyTest_FIPS_140_Only(const PK_Signer &signer, const PK_Verifier &verifier);
|
||||
void EncryptionPairwiseConsistencyTest_FIPS_140_Only(const PK_Encryptor &encryptor, const PK_Decryptor &decryptor);
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,42 @@
|
||||
#ifndef CRYPTOPP_FLTRIMPL_H
|
||||
#define CRYPTOPP_FLTRIMPL_H
|
||||
|
||||
#define FILTER_BEGIN \
|
||||
switch (m_continueAt) \
|
||||
{ \
|
||||
case 0: \
|
||||
m_inputPosition = 0;
|
||||
|
||||
#define FILTER_END_NO_MESSAGE_END_NO_RETURN \
|
||||
break; \
|
||||
default: \
|
||||
assert(false); \
|
||||
}
|
||||
|
||||
#define FILTER_END_NO_MESSAGE_END \
|
||||
FILTER_END_NO_MESSAGE_END_NO_RETURN \
|
||||
return 0;
|
||||
|
||||
/*
|
||||
#define FILTER_END \
|
||||
case -1: \
|
||||
if (messageEnd && Output(-1, NULL, 0, messageEnd, blocking)) \
|
||||
return 1; \
|
||||
FILTER_END_NO_MESSAGE_END
|
||||
*/
|
||||
|
||||
#define FILTER_OUTPUT2(site, statement, output, length, messageEnd) \
|
||||
{\
|
||||
case site: \
|
||||
statement; \
|
||||
if (Output(site, output, length, messageEnd, blocking)) \
|
||||
return STDMAX(1U, (unsigned int)length-m_inputPosition);\
|
||||
}
|
||||
|
||||
#define FILTER_OUTPUT(site, output, length, messageEnd) \
|
||||
FILTER_OUTPUT2(site, 0, output, length, messageEnd)
|
||||
|
||||
#define FILTER_OUTPUT_BYTE(site, output) \
|
||||
FILTER_OUTPUT(site, &(const byte &)(byte)output, 1, 0)
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,32 @@
|
||||
// hex.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
#include "hex.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
static const byte s_vecUpper[] = "0123456789ABCDEF";
|
||||
static const byte s_vecLower[] = "0123456789abcdef";
|
||||
|
||||
void HexEncoder::IsolatedInitialize(const NameValuePairs ¶meters)
|
||||
{
|
||||
bool uppercase = parameters.GetValueWithDefault("Uppercase", true);
|
||||
m_filter->Initialize(CombinedNameValuePairs(
|
||||
parameters,
|
||||
MakeParameters("EncodingLookupArray", uppercase ? &s_vecUpper[0] : &s_vecLower[0])("Log2Base", 4)));
|
||||
}
|
||||
|
||||
const int *HexDecoder::GetDecodingLookupArray()
|
||||
{
|
||||
static bool s_initialized = false;
|
||||
static int s_array[256];
|
||||
|
||||
if (!s_initialized)
|
||||
{
|
||||
InitializeDecodingLookupArray(s_array, s_vecUpper, 16, true);
|
||||
s_initialized = true;
|
||||
}
|
||||
return s_array;
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -0,0 +1,36 @@
|
||||
#ifndef CRYPTOPP_HEX_H
|
||||
#define CRYPTOPP_HEX_H
|
||||
|
||||
#include "basecode.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
//! Converts given data to base 16
|
||||
class HexEncoder : public SimpleProxyFilter
|
||||
{
|
||||
public:
|
||||
HexEncoder(BufferedTransformation *attachment = NULL, bool uppercase = true, int outputGroupSize = 0, const std::string &separator = ":", const std::string &terminator = "")
|
||||
: SimpleProxyFilter(new BaseN_Encoder(new Grouper), attachment)
|
||||
{
|
||||
IsolatedInitialize(MakeParameters("Uppercase", uppercase)("GroupSize", outputGroupSize)("Separator", ConstByteArrayParameter(separator)));
|
||||
}
|
||||
|
||||
void IsolatedInitialize(const NameValuePairs ¶meters);
|
||||
};
|
||||
|
||||
//! Decode base 16 data back to bytes
|
||||
class HexDecoder : public BaseN_Decoder
|
||||
{
|
||||
public:
|
||||
HexDecoder(BufferedTransformation *attachment = NULL)
|
||||
: BaseN_Decoder(GetDecodingLookupArray(), 4, attachment) {}
|
||||
|
||||
void IsolatedInitialize(const NameValuePairs ¶meters) {}
|
||||
|
||||
private:
|
||||
static const int *GetDecodingLookupArray();
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,439 @@
|
||||
#ifndef CRYPTOPP_INTEGER_H
|
||||
#define CRYPTOPP_INTEGER_H
|
||||
|
||||
/** \file */
|
||||
|
||||
#include "cryptlib.h"
|
||||
#include "secblock.h"
|
||||
|
||||
#include <iosfwd>
|
||||
#include <algorithm>
|
||||
|
||||
#ifdef _M_IX86
|
||||
# if (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 500)) || (defined(__ICL) && (__ICL >= 500))
|
||||
# define SSE2_INTRINSICS_AVAILABLE
|
||||
# elif defined(_MSC_VER)
|
||||
// _mm_free seems to be the only way to tell if the Processor Pack is installed or not
|
||||
# include <malloc.h>
|
||||
# if defined(_mm_free)
|
||||
# define SSE2_INTRINSICS_AVAILABLE
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
#ifdef SSE2_INTRINSICS_AVAILABLE
|
||||
template <class T>
|
||||
class AlignedAllocator : public AllocatorBase<T>
|
||||
{
|
||||
public:
|
||||
CRYPTOPP_INHERIT_ALLOCATOR_TYPES
|
||||
|
||||
pointer allocate(size_type n, const void *);
|
||||
void deallocate(void *p, size_type n);
|
||||
pointer reallocate(T *p, size_type oldSize, size_type newSize, bool preserve)
|
||||
{
|
||||
return StandardReallocate(*this, p, oldSize, newSize, preserve);
|
||||
}
|
||||
};
|
||||
typedef SecBlock<word, AlignedAllocator<word> > SecAlignedWordBlock;
|
||||
#else
|
||||
typedef SecWordBlock SecAlignedWordBlock;
|
||||
#endif
|
||||
|
||||
//! multiple precision integer and basic arithmetics
|
||||
/*! This class can represent positive and negative integers
|
||||
with absolute value less than (256**sizeof(word)) ** (256**sizeof(int)).
|
||||
\nosubgrouping
|
||||
*/
|
||||
class Integer : public ASN1Object
|
||||
{
|
||||
public:
|
||||
//! \name ENUMS, EXCEPTIONS, and TYPEDEFS
|
||||
//@{
|
||||
//! division by zero exception
|
||||
class DivideByZero : public Exception
|
||||
{
|
||||
public:
|
||||
DivideByZero() : Exception(OTHER_ERROR, "Integer: division by zero") {}
|
||||
};
|
||||
|
||||
//!
|
||||
class RandomNumberNotFound : public Exception
|
||||
{
|
||||
public:
|
||||
RandomNumberNotFound() : Exception(OTHER_ERROR, "Integer: no integer satisfies the given parameters") {}
|
||||
};
|
||||
|
||||
//!
|
||||
enum Sign {POSITIVE=0, NEGATIVE=1};
|
||||
|
||||
//!
|
||||
enum Signedness {
|
||||
//!
|
||||
UNSIGNED,
|
||||
//!
|
||||
SIGNED};
|
||||
|
||||
//!
|
||||
enum RandomNumberType {
|
||||
//!
|
||||
ANY,
|
||||
//!
|
||||
PRIME};
|
||||
//@}
|
||||
|
||||
//! \name CREATORS
|
||||
//@{
|
||||
//! creates the zero integer
|
||||
Integer();
|
||||
|
||||
//! copy constructor
|
||||
Integer(const Integer& t);
|
||||
|
||||
//! convert from signed long
|
||||
Integer(signed long value);
|
||||
|
||||
//! convert from two words
|
||||
Integer(Sign s, word highWord, word lowWord);
|
||||
|
||||
//! convert from string
|
||||
/*! str can be in base 2, 8, 10, or 16. Base is determined by a
|
||||
case insensitive suffix of 'h', 'o', or 'b'. No suffix means base 10.
|
||||
*/
|
||||
explicit Integer(const char *str);
|
||||
explicit Integer(const wchar_t *str);
|
||||
|
||||
//! convert from big-endian byte array
|
||||
Integer(const byte *encodedInteger, unsigned int byteCount, Signedness s=UNSIGNED);
|
||||
|
||||
//! convert from big-endian form stored in a BufferedTransformation
|
||||
Integer(BufferedTransformation &bt, unsigned int byteCount, Signedness s=UNSIGNED);
|
||||
|
||||
//! convert from BER encoded byte array stored in a BufferedTransformation object
|
||||
explicit Integer(BufferedTransformation &bt);
|
||||
|
||||
//! create a random integer
|
||||
/*! The random integer created is uniformly distributed over [0, 2**bitcount). */
|
||||
Integer(RandomNumberGenerator &rng, unsigned int bitcount);
|
||||
|
||||
//! avoid calling constructors for these frequently used integers
|
||||
static const Integer &Zero();
|
||||
//! avoid calling constructors for these frequently used integers
|
||||
static const Integer &One();
|
||||
//! avoid calling constructors for these frequently used integers
|
||||
static const Integer &Two();
|
||||
|
||||
//! create a random integer of special type
|
||||
/*! Ideally, the random integer created should be uniformly distributed
|
||||
over {x | min <= x <= max and x is of rnType and x % mod == equiv}.
|
||||
However the actual distribution may not be uniform because sequential
|
||||
search is used to find an appropriate number from a random starting
|
||||
point.
|
||||
May return (with very small probability) a pseudoprime when a prime
|
||||
is requested and max > lastSmallPrime*lastSmallPrime (lastSmallPrime
|
||||
is declared in nbtheory.h).
|
||||
\throw RandomNumberNotFound if the set is empty.
|
||||
*/
|
||||
Integer(RandomNumberGenerator &rng, const Integer &min, const Integer &max, RandomNumberType rnType=ANY, const Integer &equiv=Zero(), const Integer &mod=One());
|
||||
|
||||
//! return the integer 2**e
|
||||
static Integer Power2(unsigned int e);
|
||||
//@}
|
||||
|
||||
//! \name ENCODE/DECODE
|
||||
//@{
|
||||
//! minimum number of bytes to encode this integer
|
||||
/*! MinEncodedSize of 0 is 1 */
|
||||
unsigned int MinEncodedSize(Signedness=UNSIGNED) const;
|
||||
//! encode in big-endian format
|
||||
/*! unsigned means encode absolute value, signed means encode two's complement if negative.
|
||||
if outputLen < MinEncodedSize, the most significant bytes will be dropped
|
||||
if outputLen > MinEncodedSize, the most significant bytes will be padded
|
||||
*/
|
||||
unsigned int Encode(byte *output, unsigned int outputLen, Signedness=UNSIGNED) const;
|
||||
//!
|
||||
unsigned int Encode(BufferedTransformation &bt, unsigned int outputLen, Signedness=UNSIGNED) const;
|
||||
|
||||
//! encode using Distinguished Encoding Rules, put result into a BufferedTransformation object
|
||||
void DEREncode(BufferedTransformation &bt) const;
|
||||
|
||||
//! encode absolute value as big-endian octet string
|
||||
void DEREncodeAsOctetString(BufferedTransformation &bt, unsigned int length) const;
|
||||
|
||||
//! encode absolute value in OpenPGP format, return length of output
|
||||
unsigned int OpenPGPEncode(byte *output, unsigned int bufferSize) const;
|
||||
//! encode absolute value in OpenPGP format, put result into a BufferedTransformation object
|
||||
unsigned int OpenPGPEncode(BufferedTransformation &bt) const;
|
||||
|
||||
//!
|
||||
void Decode(const byte *input, unsigned int inputLen, Signedness=UNSIGNED);
|
||||
//!
|
||||
//* Precondition: bt.MaxRetrievable() >= inputLen
|
||||
void Decode(BufferedTransformation &bt, unsigned int inputLen, Signedness=UNSIGNED);
|
||||
|
||||
//!
|
||||
void BERDecode(const byte *input, unsigned int inputLen);
|
||||
//!
|
||||
void BERDecode(BufferedTransformation &bt);
|
||||
|
||||
//! decode nonnegative value as big-endian octet string
|
||||
void BERDecodeAsOctetString(BufferedTransformation &bt, unsigned int length);
|
||||
|
||||
class OpenPGPDecodeErr : public Exception
|
||||
{
|
||||
public:
|
||||
OpenPGPDecodeErr() : Exception(INVALID_DATA_FORMAT, "OpenPGP decode error") {}
|
||||
};
|
||||
|
||||
//!
|
||||
void OpenPGPDecode(const byte *input, unsigned int inputLen);
|
||||
//!
|
||||
void OpenPGPDecode(BufferedTransformation &bt);
|
||||
//@}
|
||||
|
||||
//! \name ACCESSORS
|
||||
//@{
|
||||
//! return true if *this can be represented as a signed long
|
||||
bool IsConvertableToLong() const;
|
||||
//! return equivalent signed long if possible, otherwise undefined
|
||||
signed long ConvertToLong() const;
|
||||
|
||||
//! number of significant bits = floor(log2(abs(*this))) + 1
|
||||
unsigned int BitCount() const;
|
||||
//! number of significant bytes = ceiling(BitCount()/8)
|
||||
unsigned int ByteCount() const;
|
||||
//! number of significant words = ceiling(ByteCount()/sizeof(word))
|
||||
unsigned int WordCount() const;
|
||||
|
||||
//! return the i-th bit, i=0 being the least significant bit
|
||||
bool GetBit(unsigned int i) const;
|
||||
//! return the i-th byte
|
||||
byte GetByte(unsigned int i) const;
|
||||
//! return n lowest bits of *this >> i
|
||||
unsigned long GetBits(unsigned int i, unsigned int n) const;
|
||||
|
||||
//!
|
||||
bool IsZero() const {return !*this;}
|
||||
//!
|
||||
bool NotZero() const {return !IsZero();}
|
||||
//!
|
||||
bool IsNegative() const {return sign == NEGATIVE;}
|
||||
//!
|
||||
bool NotNegative() const {return !IsNegative();}
|
||||
//!
|
||||
bool IsPositive() const {return NotNegative() && NotZero();}
|
||||
//!
|
||||
bool NotPositive() const {return !IsPositive();}
|
||||
//!
|
||||
bool IsEven() const {return GetBit(0) == 0;}
|
||||
//!
|
||||
bool IsOdd() const {return GetBit(0) == 1;}
|
||||
//@}
|
||||
|
||||
//! \name MANIPULATORS
|
||||
//@{
|
||||
//!
|
||||
Integer& operator=(const Integer& t);
|
||||
|
||||
//!
|
||||
Integer& operator+=(const Integer& t);
|
||||
//!
|
||||
Integer& operator-=(const Integer& t);
|
||||
//!
|
||||
Integer& operator*=(const Integer& t) {return *this = Times(t);}
|
||||
//!
|
||||
Integer& operator/=(const Integer& t) {return *this = DividedBy(t);}
|
||||
//!
|
||||
Integer& operator%=(const Integer& t) {return *this = Modulo(t);}
|
||||
//!
|
||||
Integer& operator/=(word t) {return *this = DividedBy(t);}
|
||||
//!
|
||||
Integer& operator%=(word t) {return *this = Modulo(t);}
|
||||
|
||||
//!
|
||||
Integer& operator<<=(unsigned int);
|
||||
//!
|
||||
Integer& operator>>=(unsigned int);
|
||||
|
||||
//!
|
||||
void Randomize(RandomNumberGenerator &rng, unsigned int bitcount);
|
||||
//!
|
||||
void Randomize(RandomNumberGenerator &rng, const Integer &min, const Integer &max);
|
||||
//! set this Integer to a random element of {x | min <= x <= max and x is of rnType and x % mod == equiv}
|
||||
/*! returns false if the set is empty */
|
||||
bool Randomize(RandomNumberGenerator &rng, const Integer &min, const Integer &max, RandomNumberType rnType, const Integer &equiv=Zero(), const Integer &mod=One());
|
||||
|
||||
bool GenerateRandomNoThrow(RandomNumberGenerator &rng, const NameValuePairs ¶ms = g_nullNameValuePairs);
|
||||
void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs ¶ms = g_nullNameValuePairs)
|
||||
{
|
||||
if (!GenerateRandomNoThrow(rng, params))
|
||||
throw RandomNumberNotFound();
|
||||
}
|
||||
|
||||
//! set the n-th bit to value
|
||||
void SetBit(unsigned int n, bool value=1);
|
||||
//! set the n-th byte to value
|
||||
void SetByte(unsigned int n, byte value);
|
||||
|
||||
//!
|
||||
void Negate();
|
||||
//!
|
||||
void SetPositive() {sign = POSITIVE;}
|
||||
//!
|
||||
void SetNegative() {if (!!(*this)) sign = NEGATIVE;}
|
||||
|
||||
//!
|
||||
void swap(Integer &a);
|
||||
//@}
|
||||
|
||||
//! \name UNARY OPERATORS
|
||||
//@{
|
||||
//!
|
||||
bool operator!() const;
|
||||
//!
|
||||
Integer operator+() const {return *this;}
|
||||
//!
|
||||
Integer operator-() const;
|
||||
//!
|
||||
Integer& operator++();
|
||||
//!
|
||||
Integer& operator--();
|
||||
//!
|
||||
Integer operator++(int) {Integer temp = *this; ++*this; return temp;}
|
||||
//!
|
||||
Integer operator--(int) {Integer temp = *this; --*this; return temp;}
|
||||
//@}
|
||||
|
||||
//! \name BINARY OPERATORS
|
||||
//@{
|
||||
//! signed comparison
|
||||
/*! \retval -1 if *this < a
|
||||
\retval 0 if *this = a
|
||||
\retval 1 if *this > a
|
||||
*/
|
||||
int Compare(const Integer& a) const;
|
||||
|
||||
//!
|
||||
Integer Plus(const Integer &b) const;
|
||||
//!
|
||||
Integer Minus(const Integer &b) const;
|
||||
//!
|
||||
Integer Times(const Integer &b) const;
|
||||
//!
|
||||
Integer DividedBy(const Integer &b) const;
|
||||
//!
|
||||
Integer Modulo(const Integer &b) const;
|
||||
//!
|
||||
Integer DividedBy(word b) const;
|
||||
//!
|
||||
word Modulo(word b) const;
|
||||
|
||||
//!
|
||||
Integer operator>>(unsigned int n) const {return Integer(*this)>>=n;}
|
||||
//!
|
||||
Integer operator<<(unsigned int n) const {return Integer(*this)<<=n;}
|
||||
//@}
|
||||
|
||||
//! \name OTHER ARITHMETIC FUNCTIONS
|
||||
//@{
|
||||
//!
|
||||
Integer AbsoluteValue() const;
|
||||
//!
|
||||
Integer Doubled() const {return Plus(*this);}
|
||||
//!
|
||||
Integer Squared() const {return Times(*this);}
|
||||
//! extract square root, if negative return 0, else return floor of square root
|
||||
Integer SquareRoot() const;
|
||||
//! return whether this integer is a perfect square
|
||||
bool IsSquare() const;
|
||||
|
||||
//! is 1 or -1
|
||||
bool IsUnit() const;
|
||||
//! return inverse if 1 or -1, otherwise return 0
|
||||
Integer MultiplicativeInverse() const;
|
||||
|
||||
//! modular multiplication
|
||||
friend Integer a_times_b_mod_c(const Integer &x, const Integer& y, const Integer& m);
|
||||
//! modular exponentiation
|
||||
friend Integer a_exp_b_mod_c(const Integer &x, const Integer& e, const Integer& m);
|
||||
|
||||
//! calculate r and q such that (a == d*q + r) && (0 <= r < abs(d))
|
||||
static void Divide(Integer &r, Integer &q, const Integer &a, const Integer &d);
|
||||
//! use a faster division algorithm when divisor is short
|
||||
static void Divide(word &r, Integer &q, const Integer &a, word d);
|
||||
|
||||
//! returns same result as Divide(r, q, a, Power2(n)), but faster
|
||||
static void DivideByPowerOf2(Integer &r, Integer &q, const Integer &a, unsigned int n);
|
||||
|
||||
//! greatest common divisor
|
||||
static Integer Gcd(const Integer &a, const Integer &n);
|
||||
//! calculate multiplicative inverse of *this mod n
|
||||
Integer InverseMod(const Integer &n) const;
|
||||
//!
|
||||
word InverseMod(word n) const;
|
||||
//@}
|
||||
|
||||
//! \name INPUT/OUTPUT
|
||||
//@{
|
||||
//!
|
||||
friend std::istream& operator>>(std::istream& in, Integer &a);
|
||||
//!
|
||||
friend std::ostream& operator<<(std::ostream& out, const Integer &a);
|
||||
//@}
|
||||
|
||||
private:
|
||||
friend class ModularArithmetic;
|
||||
friend class MontgomeryRepresentation;
|
||||
friend class HalfMontgomeryRepresentation;
|
||||
|
||||
Integer(word value, unsigned int length);
|
||||
|
||||
int PositiveCompare(const Integer &t) const;
|
||||
friend void PositiveAdd(Integer &sum, const Integer &a, const Integer &b);
|
||||
friend void PositiveSubtract(Integer &diff, const Integer &a, const Integer &b);
|
||||
friend void PositiveMultiply(Integer &product, const Integer &a, const Integer &b);
|
||||
friend void PositiveDivide(Integer &remainder, Integer "ient, const Integer ÷nd, const Integer &divisor);
|
||||
|
||||
SecAlignedWordBlock reg;
|
||||
Sign sign;
|
||||
};
|
||||
|
||||
//!
|
||||
inline bool operator==(const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)==0;}
|
||||
//!
|
||||
inline bool operator!=(const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)!=0;}
|
||||
//!
|
||||
inline bool operator> (const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)> 0;}
|
||||
//!
|
||||
inline bool operator>=(const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)>=0;}
|
||||
//!
|
||||
inline bool operator< (const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)< 0;}
|
||||
//!
|
||||
inline bool operator<=(const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)<=0;}
|
||||
//!
|
||||
inline CryptoPP::Integer operator+(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.Plus(b);}
|
||||
//!
|
||||
inline CryptoPP::Integer operator-(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.Minus(b);}
|
||||
//!
|
||||
inline CryptoPP::Integer operator*(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.Times(b);}
|
||||
//!
|
||||
inline CryptoPP::Integer operator/(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.DividedBy(b);}
|
||||
//!
|
||||
inline CryptoPP::Integer operator%(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.Modulo(b);}
|
||||
//!
|
||||
inline CryptoPP::Integer operator/(const CryptoPP::Integer &a, CryptoPP::word b) {return a.DividedBy(b);}
|
||||
//!
|
||||
inline CryptoPP::word operator%(const CryptoPP::Integer &a, CryptoPP::word b) {return a.Modulo(b);}
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
NAMESPACE_BEGIN(std)
|
||||
template<> inline void swap(CryptoPP::Integer &a, CryptoPP::Integer &b)
|
||||
{
|
||||
a.swap(b);
|
||||
}
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,122 @@
|
||||
// iterhash.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
#include "iterhash.h"
|
||||
#include "misc.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
template <class T, class BASE>
|
||||
IteratedHashBase<T, BASE>::IteratedHashBase(unsigned int blockSize, unsigned int digestSize)
|
||||
: m_data(blockSize/sizeof(T)), m_digest(digestSize/sizeof(T))
|
||||
, m_countHi(0), m_countLo(0)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T, class BASE> void IteratedHashBase<T, BASE>::Update(const byte *input, unsigned int len)
|
||||
{
|
||||
HashWordType tmp = m_countLo;
|
||||
if ((m_countLo = tmp + len) < tmp)
|
||||
m_countHi++; // carry from low to high
|
||||
m_countHi += SafeRightShift<8*sizeof(HashWordType)>(len);
|
||||
|
||||
unsigned int blockSize = BlockSize();
|
||||
unsigned int num = ModPowerOf2(tmp, blockSize);
|
||||
|
||||
if (num != 0) // process left over data
|
||||
{
|
||||
if ((num+len) >= blockSize)
|
||||
{
|
||||
memcpy((byte *)m_data.begin()+num, input, blockSize-num);
|
||||
HashBlock(m_data);
|
||||
input += (blockSize-num);
|
||||
len-=(blockSize - num);
|
||||
num=0;
|
||||
// drop through and do the rest
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy((byte *)m_data.begin()+num, input, len);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// now process the input data in blocks of blockSize bytes and save the leftovers to m_data
|
||||
if (len >= blockSize)
|
||||
{
|
||||
if (input == (byte *)m_data.begin())
|
||||
{
|
||||
assert(len == blockSize);
|
||||
HashBlock(m_data);
|
||||
return;
|
||||
}
|
||||
else 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(m_data, input, blockSize);
|
||||
HashBlock(m_data);
|
||||
input+=blockSize;
|
||||
len-=blockSize;
|
||||
} while (len >= blockSize);
|
||||
}
|
||||
|
||||
memcpy(m_data, input, len);
|
||||
}
|
||||
|
||||
template <class T, class BASE> byte * IteratedHashBase<T, BASE>::CreateUpdateSpace(unsigned int &size)
|
||||
{
|
||||
unsigned int blockSize = BlockSize();
|
||||
unsigned int num = ModPowerOf2(m_countLo, blockSize);
|
||||
size = blockSize - num;
|
||||
return (byte *)m_data.begin() + num;
|
||||
}
|
||||
|
||||
template <class T, class BASE> unsigned int IteratedHashBase<T, BASE>::HashMultipleBlocks(const T *input, unsigned int length)
|
||||
{
|
||||
unsigned int blockSize = BlockSize();
|
||||
do
|
||||
{
|
||||
HashBlock(input);
|
||||
input += blockSize/sizeof(T);
|
||||
length -= blockSize;
|
||||
}
|
||||
while (length >= blockSize);
|
||||
return length;
|
||||
}
|
||||
|
||||
template <class T, class BASE> void IteratedHashBase<T, BASE>::PadLastBlock(unsigned int lastBlockSize, byte padFirst)
|
||||
{
|
||||
unsigned int blockSize = BlockSize();
|
||||
unsigned int num = ModPowerOf2(m_countLo, blockSize);
|
||||
((byte *)m_data.begin())[num++]=padFirst;
|
||||
if (num <= lastBlockSize)
|
||||
memset((byte *)m_data.begin()+num, 0, lastBlockSize-num);
|
||||
else
|
||||
{
|
||||
memset((byte *)m_data.begin()+num, 0, blockSize-num);
|
||||
HashBlock(m_data);
|
||||
memset(m_data, 0, lastBlockSize);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class BASE> void IteratedHashBase<T, BASE>::Restart()
|
||||
{
|
||||
m_countLo = m_countHi = 0;
|
||||
Init();
|
||||
}
|
||||
|
||||
#ifdef WORD64_AVAILABLE
|
||||
template class IteratedHashBase<word64, HashTransformation>;
|
||||
template class IteratedHashBase<word64, MessageAuthenticationCode>;
|
||||
#endif
|
||||
|
||||
template class IteratedHashBase<word32, HashTransformation>;
|
||||
template class IteratedHashBase<word32, MessageAuthenticationCode>;
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -0,0 +1,121 @@
|
||||
#ifndef CRYPTOPP_ITERHASH_H
|
||||
#define CRYPTOPP_ITERHASH_H
|
||||
|
||||
#include "cryptlib.h"
|
||||
#include "secblock.h"
|
||||
#include "misc.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
template <class T, class BASE>
|
||||
class IteratedHashBase : public BASE
|
||||
{
|
||||
public:
|
||||
typedef T HashWordType;
|
||||
|
||||
IteratedHashBase(unsigned int blockSize, unsigned int digestSize);
|
||||
unsigned int DigestSize() const {return m_digest.size() * sizeof(T);};
|
||||
unsigned int OptimalBlockSize() const {return BlockSize();}
|
||||
unsigned int OptimalDataAlignment() const {return sizeof(T);}
|
||||
void Update(const byte *input, unsigned int length);
|
||||
byte * CreateUpdateSpace(unsigned int &size);
|
||||
void Restart();
|
||||
|
||||
protected:
|
||||
T GetBitCountHi() const {return (m_countLo >> (8*sizeof(T)-3)) + (m_countHi << 3);}
|
||||
T GetBitCountLo() const {return m_countLo << 3;}
|
||||
|
||||
virtual unsigned int HashMultipleBlocks(const T *input, unsigned int length);
|
||||
void PadLastBlock(unsigned int lastBlockSize, byte padFirst=0x80);
|
||||
virtual void Init() =0;
|
||||
virtual void HashBlock(const T *input) =0;
|
||||
virtual unsigned int BlockSize() const =0;
|
||||
|
||||
SecBlock<T> m_data; // Data buffer
|
||||
SecBlock<T> m_digest; // Message digest
|
||||
|
||||
private:
|
||||
T m_countLo, m_countHi;
|
||||
};
|
||||
|
||||
//! .
|
||||
template <class T, class B, class BASE>
|
||||
class IteratedHashBase2 : public IteratedHashBase<T, BASE>
|
||||
{
|
||||
public:
|
||||
IteratedHashBase2(unsigned int blockSize, unsigned int digestSize)
|
||||
: IteratedHashBase<T, BASE>(blockSize, digestSize) {}
|
||||
|
||||
typedef B ByteOrderClass;
|
||||
typedef typename IteratedHashBase<T, BASE>::HashWordType HashWordType;
|
||||
|
||||
inline static void CorrectEndianess(HashWordType *out, const HashWordType *in, unsigned int byteCount)
|
||||
{
|
||||
ConditionalByteReverse(B::ToEnum(), out, in, byteCount);
|
||||
}
|
||||
|
||||
void TruncatedFinal(byte *hash, unsigned int size);
|
||||
|
||||
protected:
|
||||
void HashBlock(const HashWordType *input);
|
||||
|
||||
virtual void vTransform(const HashWordType *data) =0;
|
||||
};
|
||||
|
||||
//! .
|
||||
template <class T, class B, unsigned int S, class BASE = HashTransformation>
|
||||
class IteratedHash : public IteratedHashBase2<T, B, BASE>
|
||||
{
|
||||
public:
|
||||
enum {BLOCKSIZE = S};
|
||||
|
||||
private:
|
||||
CRYPTOPP_COMPILE_ASSERT((BLOCKSIZE & (BLOCKSIZE - 1)) == 0); // blockSize is a power of 2
|
||||
|
||||
protected:
|
||||
IteratedHash(unsigned int digestSize) : IteratedHashBase2<T, B, BASE>(BLOCKSIZE, digestSize) {}
|
||||
unsigned int BlockSize() const {return BLOCKSIZE;}
|
||||
};
|
||||
|
||||
template <class T, class B, unsigned int S, class M>
|
||||
class IteratedHashWithStaticTransform : public IteratedHash<T, B, S>
|
||||
{
|
||||
protected:
|
||||
IteratedHashWithStaticTransform(unsigned int digestSize) : IteratedHash<T, B, S>(digestSize) {}
|
||||
void vTransform(const T *data) {M::Transform(m_digest, data);}
|
||||
std::string AlgorithmName() const {return M::StaticAlgorithmName();}
|
||||
};
|
||||
|
||||
// *************************************************************
|
||||
|
||||
template <class T, class B, class BASE> void IteratedHashBase2<T, B, BASE>::TruncatedFinal(byte *hash, unsigned int size)
|
||||
{
|
||||
ThrowIfInvalidTruncatedSize(size);
|
||||
|
||||
PadLastBlock(BlockSize() - 2*sizeof(HashWordType));
|
||||
CorrectEndianess(m_data, m_data, BlockSize() - 2*sizeof(HashWordType));
|
||||
|
||||
m_data[m_data.size()-2] = B::ToEnum() ? GetBitCountHi() : GetBitCountLo();
|
||||
m_data[m_data.size()-1] = B::ToEnum() ? GetBitCountLo() : GetBitCountHi();
|
||||
|
||||
vTransform(m_data);
|
||||
CorrectEndianess(m_digest, m_digest, DigestSize());
|
||||
memcpy(hash, m_digest, size);
|
||||
|
||||
Restart(); // reinit for next use
|
||||
}
|
||||
|
||||
template <class T, class B, class BASE> void IteratedHashBase2<T, B, BASE>::HashBlock(const HashWordType *input)
|
||||
{
|
||||
if (NativeByteOrderIs(B::ToEnum()))
|
||||
vTransform(input);
|
||||
else
|
||||
{
|
||||
ByteReverse(m_data.begin(), input, BlockSize());
|
||||
vTransform(m_data);
|
||||
}
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,115 @@
|
||||
// md5.cpp - modified by Wei Dai from Colin Plumb's public domain md5.c
|
||||
// any modifications are placed in the public domain
|
||||
|
||||
#include "pch.h"
|
||||
#include "md5.h"
|
||||
#include "misc.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
void MD5_TestInstantiations()
|
||||
{
|
||||
MD5 x;
|
||||
}
|
||||
|
||||
void MD5::Init()
|
||||
{
|
||||
m_digest[0] = 0x67452301L;
|
||||
m_digest[1] = 0xefcdab89L;
|
||||
m_digest[2] = 0x98badcfeL;
|
||||
m_digest[3] = 0x10325476L;
|
||||
}
|
||||
|
||||
void MD5::Transform (word32 *digest, const word32 *in)
|
||||
{
|
||||
// #define F1(x, y, z) (x & y | ~x & z)
|
||||
#define F1(x, y, z) (z ^ (x & (y ^ z)))
|
||||
#define F2(x, y, z) F1(z, x, y)
|
||||
#define F3(x, y, z) (x ^ y ^ z)
|
||||
#define F4(x, y, z) (y ^ (x | ~z))
|
||||
|
||||
#define MD5STEP(f, w, x, y, z, data, s) \
|
||||
w = rotlFixed(w + f(x, y, z) + data, s) + x
|
||||
|
||||
word32 a, b, c, d;
|
||||
|
||||
a=digest[0];
|
||||
b=digest[1];
|
||||
c=digest[2];
|
||||
d=digest[3];
|
||||
|
||||
MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
|
||||
|
||||
MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
|
||||
|
||||
MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
|
||||
|
||||
MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
|
||||
|
||||
digest[0]+=a;
|
||||
digest[1]+=b;
|
||||
digest[2]+=c;
|
||||
digest[3]+=d;
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -0,0 +1,24 @@
|
||||
#ifndef CRYPTOPP_MD5_H
|
||||
#define CRYPTOPP_MD5_H
|
||||
|
||||
#include "iterhash.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
//! <a href="http://www.weidai.com/scan-mirror/md.html#MD5">MD5</a>
|
||||
/*! 128 Bit Hash */
|
||||
class MD5 : public IteratedHashWithStaticTransform<word32, LittleEndian, 64, MD5>
|
||||
{
|
||||
public:
|
||||
enum {DIGESTSIZE = 16};
|
||||
MD5() : IteratedHashWithStaticTransform<word32, LittleEndian, 64, MD5>(DIGESTSIZE) {Init();}
|
||||
static void Transform(word32 *digest, const word32 *data);
|
||||
static const char * StaticAlgorithmName() {return "MD5";}
|
||||
|
||||
protected:
|
||||
void Init();
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,72 @@
|
||||
// mdc.h - written and placed in the public domain by Wei Dai
|
||||
|
||||
#ifndef CRYPTOPP_MDC_H
|
||||
#define CRYPTOPP_MDC_H
|
||||
|
||||
/** \file
|
||||
*/
|
||||
|
||||
#include "seckey.h"
|
||||
#include "misc.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
template <class T>
|
||||
struct MDC_Info : public FixedBlockSize<T::DIGESTSIZE>, public FixedKeyLength<T::BLOCKSIZE>
|
||||
{
|
||||
static std::string StaticAlgorithmName() {return std::string("MDC/")+T::StaticAlgorithmName();}
|
||||
};
|
||||
|
||||
//! <a href="http://www.weidai.com/scan-mirror/cs.html#MDC">MDC</a>
|
||||
/*! a construction by Peter Gutmann to turn an iterated hash function into a PRF */
|
||||
template <class T>
|
||||
class MDC : public MDC_Info<T>
|
||||
{
|
||||
class Enc : public BlockCipherBaseTemplate<MDC_Info<T> >
|
||||
{
|
||||
typedef typename T::HashWordType HashWordType;
|
||||
|
||||
public:
|
||||
void UncheckedSetKey(CipherDir direction, const byte *userKey, unsigned int length)
|
||||
{
|
||||
assert(direction == ENCRYPTION);
|
||||
AssertValidKeyLength(length);
|
||||
memcpy(Key(), userKey, KEYLENGTH);
|
||||
T::CorrectEndianess(Key(), Key(), KEYLENGTH);
|
||||
}
|
||||
|
||||
void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
|
||||
{
|
||||
T::CorrectEndianess(Buffer(), (HashWordType *)inBlock, BLOCKSIZE);
|
||||
T::Transform(Buffer(), Key());
|
||||
if (xorBlock)
|
||||
{
|
||||
T::CorrectEndianess(Buffer(), Buffer(), BLOCKSIZE);
|
||||
xorbuf(outBlock, xorBlock, m_buffer, BLOCKSIZE);
|
||||
}
|
||||
else
|
||||
T::CorrectEndianess((HashWordType *)outBlock, Buffer(), BLOCKSIZE);
|
||||
}
|
||||
|
||||
bool IsPermutation() const {return false;}
|
||||
|
||||
unsigned int GetAlignment() const {return sizeof(HashWordType);}
|
||||
|
||||
private:
|
||||
HashWordType *Key() {return (HashWordType *)m_key.data();}
|
||||
const HashWordType *Key() const {return (const HashWordType *)m_key.data();}
|
||||
HashWordType *Buffer() const {return (HashWordType *)m_buffer.data();}
|
||||
|
||||
// VC60 workaround: bug triggered if using FixedSizeAllocatorWithCleanup
|
||||
FixedSizeSecBlock<byte, MDC_Info<T>::KEYLENGTH, AllocatorWithCleanup<byte> > m_key;
|
||||
mutable FixedSizeSecBlock<byte, MDC_Info<T>::BLOCKSIZE, AllocatorWithCleanup<byte> > m_buffer;
|
||||
};
|
||||
|
||||
public:
|
||||
//! use BlockCipher interface
|
||||
typedef BlockCipherTemplate<ENCRYPTION, Enc> Encryption;
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,83 @@
|
||||
// misc.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
#include "misc.h"
|
||||
#include "words.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
byte OAEP_P_DEFAULT[1];
|
||||
|
||||
template<> void ByteReverse(word16 *, const word16 *, unsigned int);
|
||||
template<> void ByteReverse(word32 *, const word32 *, unsigned int);
|
||||
#ifdef WORD64_AVAILABLE
|
||||
template<> void ByteReverse(word64 *, const word64 *, unsigned int);
|
||||
#endif
|
||||
|
||||
void xorbuf(byte *buf, const byte *mask, unsigned int count)
|
||||
{
|
||||
if (((unsigned int)buf | (unsigned int)mask | count) % WORD_SIZE == 0)
|
||||
XorWords((word *)buf, (const word *)mask, count/WORD_SIZE);
|
||||
else
|
||||
{
|
||||
for (unsigned int i=0; i<count; i++)
|
||||
buf[i] ^= mask[i];
|
||||
}
|
||||
}
|
||||
|
||||
void xorbuf(byte *output, const byte *input, const byte *mask, unsigned int count)
|
||||
{
|
||||
if (((unsigned int)output | (unsigned int)input | (unsigned int)mask | count) % WORD_SIZE == 0)
|
||||
XorWords((word *)output, (const word *)input, (const word *)mask, count/WORD_SIZE);
|
||||
else
|
||||
{
|
||||
for (unsigned int i=0; i<count; i++)
|
||||
output[i] = input[i] ^ mask[i];
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int Parity(unsigned long value)
|
||||
{
|
||||
for (unsigned int i=8*sizeof(value)/2; i>0; i/=2)
|
||||
value ^= value >> i;
|
||||
return (unsigned int)value&1;
|
||||
}
|
||||
|
||||
unsigned int BytePrecision(unsigned long value)
|
||||
{
|
||||
unsigned int i;
|
||||
for (i=sizeof(value); i; --i)
|
||||
if (value >> (i-1)*8)
|
||||
break;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
unsigned int BitPrecision(unsigned long value)
|
||||
{
|
||||
if (!value)
|
||||
return 0;
|
||||
|
||||
unsigned int l=0, h=8*sizeof(value);
|
||||
|
||||
while (h-l > 1)
|
||||
{
|
||||
unsigned int t = (l+h)/2;
|
||||
if (value >> t)
|
||||
l = t;
|
||||
else
|
||||
h = t;
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
unsigned long Crop(unsigned long value, unsigned int size)
|
||||
{
|
||||
if (size < 8*sizeof(value))
|
||||
return (value & ((1L << size) - 1));
|
||||
else
|
||||
return value;
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -0,0 +1,688 @@
|
||||
#ifndef CRYPTOPP_MISC_H
|
||||
#define CRYPTOPP_MISC_H
|
||||
|
||||
#include "config.h"
|
||||
#include "cryptlib.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)
|
||||
|
||||
// ************** compile-time assertion ***************
|
||||
|
||||
template <bool b>
|
||||
struct CompileAssert
|
||||
{
|
||||
static char dummy[2*b-1];
|
||||
};
|
||||
|
||||
#define CRYPTOPP_COMPILE_ASSERT(assertion) CRYPTOPP_COMPILE_ASSERT_INSTANCE(assertion, __LINE__)
|
||||
#define CRYPTOPP_COMPILE_ASSERT_INSTANCE(assertion, instance) static CompileAssert<(assertion)> CRYPTOPP_ASSERT_JOIN(cryptopp_assert_, instance)
|
||||
#define CRYPTOPP_ASSERT_JOIN(X, Y) CRYPTOPP_DO_ASSERT_JOIN(X, Y)
|
||||
#define CRYPTOPP_DO_ASSERT_JOIN(X, Y) X##Y
|
||||
|
||||
// ************** misc classes ***************
|
||||
|
||||
class Empty
|
||||
{
|
||||
};
|
||||
|
||||
template <class BASE1, class BASE2>
|
||||
class TwoBases : public BASE1, public BASE2
|
||||
{
|
||||
};
|
||||
|
||||
template <class BASE1, class BASE2, class BASE3>
|
||||
class ThreeBases : public BASE1, public BASE2, public BASE3
|
||||
{
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class ObjectHolder
|
||||
{
|
||||
protected:
|
||||
T m_object;
|
||||
};
|
||||
|
||||
class NotCopyable
|
||||
{
|
||||
public:
|
||||
NotCopyable() {}
|
||||
private:
|
||||
NotCopyable(const NotCopyable &);
|
||||
void operator=(const NotCopyable &);
|
||||
};
|
||||
|
||||
// ************** misc functions ***************
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
#define RETURN_IF_NONZERO(x) unsigned int returnedValue = x; if (returnedValue) return returnedValue
|
||||
|
||||
// this version of the macro is fastest on Pentium 3 and Pentium 4 with MSVC 6 SP5 w/ Processor Pack
|
||||
#define GETBYTE(x, y) (unsigned int)byte((x)>>(8*(y)))
|
||||
// these may be faster on other CPUs/compilers
|
||||
// #define GETBYTE(x, y) (unsigned int)(((x)>>(8*(y)))&255)
|
||||
// #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);
|
||||
|
||||
template <class T>
|
||||
inline bool IsPowerOf2(T n)
|
||||
{
|
||||
return n > 0 && (n & (n-1)) == 0;
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
inline T2 ModPowerOf2(T1 a, T2 b)
|
||||
{
|
||||
assert(IsPowerOf2(b));
|
||||
return T2(a) & (b-1);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T RoundDownToMultipleOf(T n, T m)
|
||||
{
|
||||
return n - (IsPowerOf2(m) ? ModPowerOf2(n, m) : (n%m));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T RoundUpToMultipleOf(T n, T m)
|
||||
{
|
||||
return RoundDownToMultipleOf(n+m-1, m);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline unsigned int GetAlignment(T *dummy=NULL) // VC60 workaround
|
||||
{
|
||||
#if (_MSC_VER >= 1300)
|
||||
return __alignof(T);
|
||||
#elif defined(__GNUC__)
|
||||
return __alignof__(T);
|
||||
#else
|
||||
return sizeof(T);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline bool IsAlignedOn(const void *p, unsigned int alignment)
|
||||
{
|
||||
return IsPowerOf2(alignment) ? ModPowerOf2((unsigned int)p, alignment) == 0 : (unsigned int)p % alignment == 0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline bool IsAligned(const void *p, T *dummy=NULL) // VC60 workaround
|
||||
{
|
||||
return IsAlignedOn(p, GetAlignment<T>());
|
||||
}
|
||||
|
||||
#ifdef IS_LITTLE_ENDIAN
|
||||
typedef LittleEndian NativeByteOrder;
|
||||
#else
|
||||
typedef BigEndian NativeByteOrder;
|
||||
#endif
|
||||
|
||||
inline ByteOrder GetNativeByteOrder()
|
||||
{
|
||||
return NativeByteOrder::ToEnum();
|
||||
}
|
||||
|
||||
inline bool NativeByteOrderIs(ByteOrder order)
|
||||
{
|
||||
return order == GetNativeByteOrder();
|
||||
}
|
||||
|
||||
template <class T> // can't use <sstream> because GCC 2.95.2 doesn't have it
|
||||
std::string IntToString(T a, unsigned int base = 10)
|
||||
{
|
||||
if (a == 0)
|
||||
return "0";
|
||||
bool negate = false;
|
||||
if (a < 0)
|
||||
{
|
||||
negate = true;
|
||||
a = 0-a; // VC .NET does not like -a
|
||||
}
|
||||
std::string result;
|
||||
while (a > 0)
|
||||
{
|
||||
T digit = a % base;
|
||||
result = char((digit < 10 ? '0' : ('a' - 10)) + digit) + result;
|
||||
a /= base;
|
||||
}
|
||||
if (negate)
|
||||
result = "-" + result;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
inline T1 SaturatingSubtract(T1 a, T2 b)
|
||||
{
|
||||
CRYPTOPP_COMPILE_ASSERT_INSTANCE(T1(-1)>0, 0); // T1 is unsigned type
|
||||
CRYPTOPP_COMPILE_ASSERT_INSTANCE(T2(-1)>0, 1); // T2 is unsigned type
|
||||
return T1((a > b) ? (a - b) : 0);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline CipherDir GetCipherDir(const T &obj)
|
||||
{
|
||||
return obj.IsForwardTransformation() ? ENCRYPTION : DECRYPTION;
|
||||
}
|
||||
|
||||
// ************** 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
|
||||
|
||||
#pragma intrinsic(_lrotl, _lrotr)
|
||||
|
||||
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 ***************
|
||||
|
||||
template <class T>
|
||||
inline unsigned int GetByte(ByteOrder order, T value, unsigned int index)
|
||||
{
|
||||
if (order == LITTLE_ENDIAN_ORDER)
|
||||
return GETBYTE(value, index);
|
||||
else
|
||||
return GETBYTE(value, sizeof(T)-index-1);
|
||||
}
|
||||
|
||||
inline byte ByteReverse(byte value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
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 (T)BitReverse((byte)value);
|
||||
else if (sizeof(T) == 2)
|
||||
return (T)BitReverse((word16)value);
|
||||
else if (sizeof(T) == 4)
|
||||
return (T)BitReverse((word32)value);
|
||||
else
|
||||
{
|
||||
#ifdef WORD64_AVAILABLE
|
||||
assert(sizeof(T) == 8);
|
||||
return (T)BitReverse((word64)value);
|
||||
#else
|
||||
assert(false);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T ConditionalByteReverse(ByteOrder order, T value)
|
||||
{
|
||||
return NativeByteOrderIs(order) ? value : ByteReverse(value);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void ByteReverse(T *out, const T *in, unsigned int byteCount)
|
||||
{
|
||||
assert(byteCount % sizeof(T) == 0);
|
||||
unsigned int count = byteCount/sizeof(T);
|
||||
for (unsigned int i=0; i<count; i++)
|
||||
out[i] = ByteReverse(in[i]);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void ConditionalByteReverse(ByteOrder order, T *out, const T *in, unsigned int byteCount)
|
||||
{
|
||||
if (!NativeByteOrderIs(order))
|
||||
ByteReverse(out, in, byteCount);
|
||||
else if (in != out)
|
||||
memcpy(out, in, byteCount);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void GetUserKey(ByteOrder order, 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);
|
||||
ConditionalByteReverse(order, out, out, RoundUpToMultipleOf(inlen, U));
|
||||
}
|
||||
|
||||
inline byte UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, byte*)
|
||||
{
|
||||
return block[0];
|
||||
}
|
||||
|
||||
inline word16 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, word16*)
|
||||
{
|
||||
return (order == BIG_ENDIAN_ORDER)
|
||||
? block[1] | (block[0] << 8)
|
||||
: block[0] | (block[1] << 8);
|
||||
}
|
||||
|
||||
inline word32 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, word32*)
|
||||
{
|
||||
return (order == BIG_ENDIAN_ORDER)
|
||||
? word32(block[3]) | (word32(block[2]) << 8) | (word32(block[1]) << 16) | (word32(block[0]) << 24)
|
||||
: word32(block[0]) | (word32(block[1]) << 8) | (word32(block[2]) << 16) | (word32(block[3]) << 24);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T UnalignedGetWord(ByteOrder order, const byte *block, T*dummy=NULL)
|
||||
{
|
||||
return UnalignedGetWordNonTemplate(order, block, dummy);
|
||||
}
|
||||
|
||||
inline void UnalignedPutWord(ByteOrder order, byte *block, byte value, const byte *xorBlock = NULL)
|
||||
{
|
||||
block[0] = xorBlock ? (value ^ xorBlock[0]) : value;
|
||||
}
|
||||
|
||||
inline void UnalignedPutWord(ByteOrder order, byte *block, word16 value, const byte *xorBlock = NULL)
|
||||
{
|
||||
if (order == BIG_ENDIAN_ORDER)
|
||||
{
|
||||
block[0] = GETBYTE(value, 1);
|
||||
block[1] = GETBYTE(value, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
block[0] = GETBYTE(value, 0);
|
||||
block[1] = GETBYTE(value, 1);
|
||||
}
|
||||
|
||||
if (xorBlock)
|
||||
{
|
||||
block[0] ^= xorBlock[0];
|
||||
block[1] ^= xorBlock[1];
|
||||
}
|
||||
}
|
||||
|
||||
inline void UnalignedPutWord(ByteOrder order, byte *block, word32 value, const byte *xorBlock = NULL)
|
||||
{
|
||||
if (order == BIG_ENDIAN_ORDER)
|
||||
{
|
||||
block[0] = GETBYTE(value, 3);
|
||||
block[1] = GETBYTE(value, 2);
|
||||
block[2] = GETBYTE(value, 1);
|
||||
block[3] = GETBYTE(value, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
block[0] = GETBYTE(value, 0);
|
||||
block[1] = GETBYTE(value, 1);
|
||||
block[2] = GETBYTE(value, 2);
|
||||
block[3] = GETBYTE(value, 3);
|
||||
}
|
||||
|
||||
if (xorBlock)
|
||||
{
|
||||
block[0] ^= xorBlock[0];
|
||||
block[1] ^= xorBlock[1];
|
||||
block[2] ^= xorBlock[2];
|
||||
block[3] ^= xorBlock[3];
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T GetWord(bool assumeAligned, ByteOrder order, const byte *block)
|
||||
{
|
||||
if (assumeAligned)
|
||||
{
|
||||
assert(IsAligned<T>(block));
|
||||
return ConditionalByteReverse(order, *reinterpret_cast<const T *>(block));
|
||||
}
|
||||
else
|
||||
return UnalignedGetWord<T>(order, block);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void GetWord(bool assumeAligned, ByteOrder order, T &result, const byte *block)
|
||||
{
|
||||
result = GetWord<T>(assumeAligned, order, block);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void PutWord(bool assumeAligned, ByteOrder order, byte *block, T value, const byte *xorBlock = NULL)
|
||||
{
|
||||
if (assumeAligned)
|
||||
{
|
||||
assert(IsAligned<T>(block));
|
||||
if (xorBlock)
|
||||
*reinterpret_cast<T *>(block) = ConditionalByteReverse(order, value) ^ *reinterpret_cast<const T *>(xorBlock);
|
||||
else
|
||||
*reinterpret_cast<T *>(block) = ConditionalByteReverse(order, value);
|
||||
}
|
||||
else
|
||||
UnalignedPutWord(order, block, value, xorBlock);
|
||||
}
|
||||
|
||||
template <class T, class B, bool A=true>
|
||||
class GetBlock
|
||||
{
|
||||
public:
|
||||
GetBlock(const void *block)
|
||||
: m_block((const byte *)block) {}
|
||||
|
||||
template <class U>
|
||||
inline GetBlock<T, B, A> & operator()(U &x)
|
||||
{
|
||||
CRYPTOPP_COMPILE_ASSERT(sizeof(U) >= sizeof(T));
|
||||
x = GetWord<T>(A, B::ToEnum(), m_block);
|
||||
m_block += sizeof(T);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
const byte *m_block;
|
||||
};
|
||||
|
||||
template <class T, class B, bool A=true>
|
||||
class PutBlock
|
||||
{
|
||||
public:
|
||||
PutBlock(const void *xorBlock, void *block)
|
||||
: m_xorBlock((const byte *)xorBlock), m_block((byte *)block) {}
|
||||
|
||||
template <class U>
|
||||
inline PutBlock<T, B, A> & operator()(U x)
|
||||
{
|
||||
PutWord(A, B::ToEnum(), m_block, (T)x, m_xorBlock);
|
||||
m_block += sizeof(T);
|
||||
if (m_xorBlock)
|
||||
m_xorBlock += sizeof(T);
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
const byte *m_xorBlock;
|
||||
byte *m_block;
|
||||
};
|
||||
|
||||
template <class T, class B, bool A=true>
|
||||
struct BlockGetAndPut
|
||||
{
|
||||
// function needed because of C++ grammatical ambiguity between expression-statements and declarations
|
||||
static inline GetBlock<T, B, A> Get(const void *block) {return GetBlock<T, B, A>(block);}
|
||||
typedef PutBlock<T, B, A> Put;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
std::string WordToString(T value, ByteOrder order = BIG_ENDIAN_ORDER)
|
||||
{
|
||||
if (!NativeByteOrderIs(order))
|
||||
value = ByteReverse(value);
|
||||
|
||||
return std::string((char *)&value, sizeof(value));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T StringToWord(const std::string &str, ByteOrder order = BIG_ENDIAN_ORDER)
|
||||
{
|
||||
T value = 0;
|
||||
memcpy(&value, str.data(), STDMIN(sizeof(value), str.size()));
|
||||
return NativeByteOrderIs(order) ? value : ByteReverse(value);
|
||||
}
|
||||
|
||||
// ************** help remove warning on g++ ***************
|
||||
|
||||
template <bool overflow> struct SafeShifter;
|
||||
|
||||
template<> struct SafeShifter<true>
|
||||
{
|
||||
template <class T>
|
||||
static inline T RightShift(T value, unsigned int bits)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static inline T LeftShift(T value, unsigned int bits)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct SafeShifter<false>
|
||||
{
|
||||
template <class T>
|
||||
static inline T RightShift(T value, unsigned int bits)
|
||||
{
|
||||
return value >> bits;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static inline T LeftShift(T value, unsigned int bits)
|
||||
{
|
||||
return value << bits;
|
||||
}
|
||||
};
|
||||
|
||||
template <unsigned int bits, class T>
|
||||
inline T SafeRightShift(T value)
|
||||
{
|
||||
return SafeShifter<(bits>=(8*sizeof(T)))>::RightShift(value, bits);
|
||||
}
|
||||
|
||||
template <unsigned int bits, class T>
|
||||
inline T SafeLeftShift(T value)
|
||||
{
|
||||
return SafeShifter<(bits>=(8*sizeof(T)))>::LeftShift(value, bits);
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif // MISC_H
|
||||
@@ -0,0 +1,149 @@
|
||||
#ifndef CRYPTOPP_MODARITH_H
|
||||
#define CRYPTOPP_MODARITH_H
|
||||
|
||||
// implementations are in integer.cpp
|
||||
|
||||
#include "cryptlib.h"
|
||||
#include "misc.h"
|
||||
#include "integer.h"
|
||||
#include "algebra.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
//! .
|
||||
class ModularArithmetic : public AbstractRing<Integer>
|
||||
{
|
||||
public:
|
||||
|
||||
typedef int RandomizationParameter;
|
||||
typedef Integer Element;
|
||||
|
||||
ModularArithmetic(const Integer &modulus = Integer::One())
|
||||
: modulus(modulus), result((word)0, modulus.reg.size()) {}
|
||||
|
||||
ModularArithmetic(const ModularArithmetic &ma)
|
||||
: modulus(ma.modulus), result((word)0, modulus.reg.size()) {}
|
||||
|
||||
ModularArithmetic(BufferedTransformation &bt); // construct from BER encoded parameters
|
||||
|
||||
virtual ModularArithmetic * Clone() const {return new ModularArithmetic(*this);}
|
||||
|
||||
void DEREncode(BufferedTransformation &bt) const;
|
||||
|
||||
void DEREncodeElement(BufferedTransformation &out, const Element &a) const;
|
||||
void BERDecodeElement(BufferedTransformation &in, Element &a) const;
|
||||
|
||||
const Integer& GetModulus() const {return modulus;}
|
||||
void SetModulus(const Integer &newModulus) {modulus = newModulus; result.reg.resize(modulus.reg.size());}
|
||||
|
||||
virtual bool IsMontgomeryRepresentation() const {return false;}
|
||||
|
||||
virtual Integer ConvertIn(const Integer &a) const
|
||||
{return a%modulus;}
|
||||
|
||||
virtual Integer ConvertOut(const Integer &a) const
|
||||
{return a;}
|
||||
|
||||
const Integer& Half(const Integer &a) const;
|
||||
|
||||
bool Equal(const Integer &a, const Integer &b) const
|
||||
{return a==b;}
|
||||
|
||||
const Integer& Identity() const
|
||||
{return Integer::Zero();}
|
||||
|
||||
const Integer& Add(const Integer &a, const Integer &b) const;
|
||||
|
||||
Integer& Accumulate(Integer &a, const Integer &b) const;
|
||||
|
||||
const Integer& Inverse(const Integer &a) const;
|
||||
|
||||
const Integer& Subtract(const Integer &a, const Integer &b) const;
|
||||
|
||||
Integer& Reduce(Integer &a, const Integer &b) const;
|
||||
|
||||
const Integer& Double(const Integer &a) const
|
||||
{return Add(a, a);}
|
||||
|
||||
const Integer& MultiplicativeIdentity() const
|
||||
{return Integer::One();}
|
||||
|
||||
const Integer& Multiply(const Integer &a, const Integer &b) const
|
||||
{return result1 = a*b%modulus;}
|
||||
|
||||
const Integer& Square(const Integer &a) const
|
||||
{return result1 = a.Squared()%modulus;}
|
||||
|
||||
bool IsUnit(const Integer &a) const
|
||||
{return Integer::Gcd(a, modulus).IsUnit();}
|
||||
|
||||
const Integer& MultiplicativeInverse(const Integer &a) const
|
||||
{return result1 = a.InverseMod(modulus);}
|
||||
|
||||
const Integer& Divide(const Integer &a, const Integer &b) const
|
||||
{return Multiply(a, MultiplicativeInverse(b));}
|
||||
|
||||
Integer CascadeExponentiate(const Integer &x, const Integer &e1, const Integer &y, const Integer &e2) const;
|
||||
|
||||
void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const;
|
||||
|
||||
unsigned int MaxElementBitLength() const
|
||||
{return (modulus-1).BitCount();}
|
||||
|
||||
unsigned int MaxElementByteLength() const
|
||||
{return (modulus-1).ByteCount();}
|
||||
|
||||
Element RandomElement( RandomNumberGenerator &rng , const RandomizationParameter &ignore_for_now = 0 ) const
|
||||
// left RandomizationParameter arg as ref in case RandomizationParameter becomes a more complicated struct
|
||||
{
|
||||
return Element( rng , Integer( (long) 0) , modulus - Integer( (long) 1 ) ) ;
|
||||
}
|
||||
|
||||
static const RandomizationParameter DefaultRandomizationParameter ;
|
||||
|
||||
protected:
|
||||
Integer modulus;
|
||||
mutable Integer result, result1;
|
||||
|
||||
};
|
||||
|
||||
// const ModularArithmetic::RandomizationParameter ModularArithmetic::DefaultRandomizationParameter = 0 ;
|
||||
|
||||
//! do modular arithmetics in Montgomery representation for increased speed
|
||||
class MontgomeryRepresentation : public ModularArithmetic
|
||||
{
|
||||
public:
|
||||
MontgomeryRepresentation(const Integer &modulus); // modulus must be odd
|
||||
|
||||
virtual ModularArithmetic * Clone() const {return new MontgomeryRepresentation(*this);}
|
||||
|
||||
bool IsMontgomeryRepresentation() const {return true;}
|
||||
|
||||
Integer ConvertIn(const Integer &a) const
|
||||
{return (a<<(WORD_BITS*modulus.reg.size()))%modulus;}
|
||||
|
||||
Integer ConvertOut(const Integer &a) const;
|
||||
|
||||
const Integer& MultiplicativeIdentity() const
|
||||
{return result1 = Integer::Power2(WORD_BITS*modulus.reg.size())%modulus;}
|
||||
|
||||
const Integer& Multiply(const Integer &a, const Integer &b) const;
|
||||
|
||||
const Integer& Square(const Integer &a) const;
|
||||
|
||||
const Integer& MultiplicativeInverse(const Integer &a) const;
|
||||
|
||||
Integer CascadeExponentiate(const Integer &x, const Integer &e1, const Integer &y, const Integer &e2) const
|
||||
{return AbstractRing<Integer>::CascadeExponentiate(x, e1, y, e2);}
|
||||
|
||||
void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const
|
||||
{AbstractRing<Integer>::SimultaneousExponentiate(results, base, exponents, exponentsCount);}
|
||||
|
||||
private:
|
||||
Integer u;
|
||||
mutable SecAlignedWordBlock workspace;
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,266 @@
|
||||
// modes.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
#include "modes.h"
|
||||
|
||||
#include "des.h"
|
||||
|
||||
#include "strciphr.cpp"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
void Modes_TestInstantiations()
|
||||
{
|
||||
CFB_Mode<DES>::Encryption m0;
|
||||
CFB_Mode<DES>::Decryption m1;
|
||||
OFB_Mode<DES>::Encryption m2;
|
||||
CTR_Mode<DES>::Encryption m3;
|
||||
ECB_Mode<DES>::Encryption m4;
|
||||
CBC_Mode<DES>::Encryption m5;
|
||||
}
|
||||
|
||||
// explicit instantiations for Darwin gcc-932.1
|
||||
template class CFB_CipherTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >;
|
||||
template class CFB_EncryptionTemplate<>;
|
||||
template class CFB_DecryptionTemplate<>;
|
||||
template class AdditiveCipherTemplate<>;
|
||||
template class CFB_CipherTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> >;
|
||||
template class CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> >;
|
||||
template class CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> >;
|
||||
template class AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, OFB_ModePolicy> >;
|
||||
template class AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, CTR_ModePolicy> >;
|
||||
|
||||
void CipherModeBase::SetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms)
|
||||
{
|
||||
UncheckedSetKey(params, key, length); // the underlying cipher will check the key length
|
||||
}
|
||||
|
||||
void CipherModeBase::GetNextIV(byte *IV)
|
||||
{
|
||||
if (!IsForwardTransformation())
|
||||
throw NotImplemented("CipherModeBase: GetNextIV() must be called on an encryption object");
|
||||
|
||||
m_cipher->ProcessBlock(m_register);
|
||||
memcpy(IV, m_register, BlockSize());
|
||||
}
|
||||
|
||||
void CipherModeBase::SetIV(const byte *iv)
|
||||
{
|
||||
if (iv)
|
||||
Resynchronize(iv);
|
||||
else if (IsResynchronizable())
|
||||
{
|
||||
if (!CanUseStructuredIVs())
|
||||
throw InvalidArgument("CipherModeBase: this cipher mode cannot use a null IV");
|
||||
|
||||
// use all zeros as default IV
|
||||
SecByteBlock iv(BlockSize());
|
||||
memset(iv, 0, iv.size());
|
||||
Resynchronize(iv);
|
||||
}
|
||||
}
|
||||
|
||||
void CTR_ModePolicy::SeekToIteration(dword iterationCount)
|
||||
{
|
||||
int carry=0;
|
||||
for (int i=BlockSize()-1; i>=0; i--)
|
||||
{
|
||||
unsigned int sum = m_register[i] + byte(iterationCount) + carry;
|
||||
m_counterArray[i] = (byte) sum;
|
||||
carry = sum >> 8;
|
||||
iterationCount >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void IncrementCounterByOne(byte *inout, unsigned int s)
|
||||
{
|
||||
for (int i=s-1, carry=1; i>=0 && carry; i--)
|
||||
carry = !++inout[i];
|
||||
}
|
||||
|
||||
static inline void IncrementCounterByOne(byte *output, const byte *input, unsigned int s)
|
||||
{
|
||||
for (int i=s-1, carry=1; i>=0; i--)
|
||||
carry = !(output[i] = input[i]+carry) && carry;
|
||||
}
|
||||
|
||||
inline void CTR_ModePolicy::ProcessMultipleBlocks(byte *output, const byte *input, unsigned int n)
|
||||
{
|
||||
unsigned int s = BlockSize(), j = 0;
|
||||
for (unsigned int i=1; i<n; i++, j+=s)
|
||||
IncrementCounterByOne(m_counterArray + j + s, m_counterArray + j, s);
|
||||
m_cipher->ProcessAndXorMultipleBlocks(m_counterArray, input, output, n);
|
||||
IncrementCounterByOne(m_counterArray, m_counterArray + s*(n-1), s);
|
||||
}
|
||||
|
||||
void CTR_ModePolicy::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, unsigned int iterationCount)
|
||||
{
|
||||
unsigned int maxBlocks = m_cipher->OptimalNumberOfParallelBlocks();
|
||||
if (maxBlocks == 1)
|
||||
{
|
||||
unsigned int sizeIncrement = BlockSize();
|
||||
while (iterationCount)
|
||||
{
|
||||
m_cipher->ProcessAndXorBlock(m_counterArray, input, output);
|
||||
IncrementCounterByOne(m_counterArray, sizeIncrement);
|
||||
output += sizeIncrement;
|
||||
input += sizeIncrement;
|
||||
iterationCount -= 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int sizeIncrement = maxBlocks * BlockSize();
|
||||
while (iterationCount >= maxBlocks)
|
||||
{
|
||||
ProcessMultipleBlocks(output, input, maxBlocks);
|
||||
output += sizeIncrement;
|
||||
input += sizeIncrement;
|
||||
iterationCount -= maxBlocks;
|
||||
}
|
||||
if (iterationCount > 0)
|
||||
ProcessMultipleBlocks(output, input, iterationCount);
|
||||
}
|
||||
}
|
||||
|
||||
void CTR_ModePolicy::CipherResynchronize(byte *keystreamBuffer, const byte *iv)
|
||||
{
|
||||
unsigned int s = BlockSize();
|
||||
memcpy(m_register, iv, s);
|
||||
m_counterArray.New(s * m_cipher->OptimalNumberOfParallelBlocks());
|
||||
memcpy(m_counterArray, iv, s);
|
||||
}
|
||||
|
||||
void BlockOrientedCipherModeBase::UncheckedSetKey(const NameValuePairs ¶ms, const byte *key, unsigned int length)
|
||||
{
|
||||
m_cipher->SetKey(key, length, params);
|
||||
ResizeBuffers();
|
||||
const byte *iv = params.GetValueWithDefault(Name::IV(), (const byte *)NULL);
|
||||
SetIV(iv);
|
||||
}
|
||||
|
||||
void BlockOrientedCipherModeBase::ProcessData(byte *outString, const byte *inString, unsigned int length)
|
||||
{
|
||||
unsigned int s = BlockSize();
|
||||
assert(length % s == 0);
|
||||
unsigned int alignment = m_cipher->BlockAlignment();
|
||||
bool inputAlignmentOk = !RequireAlignedInput() || IsAlignedOn(inString, alignment);
|
||||
|
||||
if (IsAlignedOn(outString, alignment))
|
||||
{
|
||||
if (inputAlignmentOk)
|
||||
ProcessBlocks(outString, inString, length / s);
|
||||
else
|
||||
{
|
||||
memcpy(outString, inString, length);
|
||||
ProcessBlocks(outString, outString, length / s);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (length)
|
||||
{
|
||||
if (inputAlignmentOk)
|
||||
ProcessBlocks(m_buffer, inString, 1);
|
||||
else
|
||||
{
|
||||
memcpy(m_buffer, inString, s);
|
||||
ProcessBlocks(m_buffer, m_buffer, 1);
|
||||
}
|
||||
memcpy(outString, m_buffer, s);
|
||||
inString += s;
|
||||
outString += s;
|
||||
length -= s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CBC_Encryption::ProcessBlocks(byte *outString, const byte *inString, unsigned int numberOfBlocks)
|
||||
{
|
||||
unsigned int blockSize = BlockSize();
|
||||
while (numberOfBlocks--)
|
||||
{
|
||||
xorbuf(m_register, inString, blockSize);
|
||||
m_cipher->ProcessBlock(m_register);
|
||||
memcpy(outString, m_register, blockSize);
|
||||
inString += blockSize;
|
||||
outString += blockSize;
|
||||
}
|
||||
}
|
||||
|
||||
void CBC_CTS_Encryption::ProcessLastBlock(byte *outString, const byte *inString, unsigned int length)
|
||||
{
|
||||
if (length <= BlockSize())
|
||||
{
|
||||
if (!m_stolenIV)
|
||||
throw InvalidArgument("CBC_Encryption: message is too short for ciphertext stealing");
|
||||
|
||||
// steal from IV
|
||||
memcpy(outString, m_register, length);
|
||||
outString = m_stolenIV;
|
||||
}
|
||||
else
|
||||
{
|
||||
// steal from next to last block
|
||||
xorbuf(m_register, inString, BlockSize());
|
||||
m_cipher->ProcessBlock(m_register);
|
||||
inString += BlockSize();
|
||||
length -= BlockSize();
|
||||
memcpy(outString+BlockSize(), m_register, length);
|
||||
}
|
||||
|
||||
// output last full ciphertext block
|
||||
xorbuf(m_register, inString, length);
|
||||
m_cipher->ProcessBlock(m_register);
|
||||
memcpy(outString, m_register, BlockSize());
|
||||
}
|
||||
|
||||
void CBC_Decryption::ProcessBlocks(byte *outString, const byte *inString, unsigned int numberOfBlocks)
|
||||
{
|
||||
unsigned int blockSize = BlockSize();
|
||||
while (numberOfBlocks--)
|
||||
{
|
||||
memcpy(m_temp, inString, blockSize);
|
||||
m_cipher->ProcessBlock(m_temp, outString);
|
||||
xorbuf(outString, m_register, blockSize);
|
||||
m_register.swap(m_temp);
|
||||
inString += blockSize;
|
||||
outString += blockSize;
|
||||
}
|
||||
}
|
||||
|
||||
void CBC_CTS_Decryption::ProcessLastBlock(byte *outString, const byte *inString, unsigned int length)
|
||||
{
|
||||
const byte *pn, *pn1;
|
||||
bool stealIV = length <= BlockSize();
|
||||
|
||||
if (stealIV)
|
||||
{
|
||||
pn = inString;
|
||||
pn1 = m_register;
|
||||
}
|
||||
else
|
||||
{
|
||||
pn = inString + BlockSize();
|
||||
pn1 = inString;
|
||||
length -= BlockSize();
|
||||
}
|
||||
|
||||
// decrypt last partial plaintext block
|
||||
memcpy(m_temp, pn1, BlockSize());
|
||||
m_cipher->ProcessBlock(m_temp);
|
||||
xorbuf(m_temp, pn, length);
|
||||
|
||||
if (stealIV)
|
||||
memcpy(outString, m_temp, length);
|
||||
else
|
||||
{
|
||||
memcpy(outString+BlockSize(), m_temp, length);
|
||||
// decrypt next to last plaintext block
|
||||
memcpy(m_temp, pn, length);
|
||||
m_cipher->ProcessBlock(m_temp);
|
||||
xorbuf(outString, m_temp, m_register, BlockSize());
|
||||
}
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -0,0 +1,370 @@
|
||||
#ifndef CRYPTOPP_MODES_H
|
||||
#define CRYPTOPP_MODES_H
|
||||
|
||||
/*! \file
|
||||
*/
|
||||
|
||||
#include "cryptlib.h"
|
||||
#include "secblock.h"
|
||||
#include "misc.h"
|
||||
#include "strciphr.h"
|
||||
#include "argnames.h"
|
||||
#include "algparam.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
//! Cipher mode documentation. See NIST SP 800-38A for definitions of these modes.
|
||||
|
||||
/*! Each class derived from this one defines two types, Encryption and Decryption,
|
||||
both of which implement the SymmetricCipher interface.
|
||||
For each mode there are two classes, one of which is a template class,
|
||||
and the other one has a name that ends in "_ExternalCipher".
|
||||
The "external cipher" mode objects hold a reference to the underlying block cipher,
|
||||
instead of holding an instance of it. The reference must be passed in to the constructor.
|
||||
For the "cipher holder" classes, the CIPHER template parameter should be a class
|
||||
derived from BlockCipherDocumentation, for example DES or AES.
|
||||
*/
|
||||
struct CipherModeDocumentation : public SymmetricCipherDocumentation
|
||||
{
|
||||
};
|
||||
|
||||
class CipherModeBase : public SymmetricCipher
|
||||
{
|
||||
public:
|
||||
unsigned int MinKeyLength() const {return m_cipher->MinKeyLength();}
|
||||
unsigned int MaxKeyLength() const {return m_cipher->MaxKeyLength();}
|
||||
unsigned int DefaultKeyLength() const {return m_cipher->DefaultKeyLength();}
|
||||
unsigned int GetValidKeyLength(unsigned int n) const {return m_cipher->GetValidKeyLength(n);}
|
||||
bool IsValidKeyLength(unsigned int n) const {return m_cipher->IsValidKeyLength(n);}
|
||||
|
||||
void SetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms = g_nullNameValuePairs);
|
||||
|
||||
unsigned int OptimalDataAlignment() const {return BlockSize();}
|
||||
|
||||
unsigned int IVSize() const {return BlockSize();}
|
||||
void GetNextIV(byte *IV);
|
||||
virtual IV_Requirement IVRequirement() const =0;
|
||||
|
||||
protected:
|
||||
inline unsigned int BlockSize() const {assert(m_register.size() > 0); return m_register.size();}
|
||||
void SetIV(const byte *iv);
|
||||
virtual void SetFeedbackSize(unsigned int feedbackSize)
|
||||
{
|
||||
if (!(feedbackSize == 0 || feedbackSize == BlockSize()))
|
||||
throw InvalidArgument("CipherModeBase: feedback size cannot be specified for this cipher mode");
|
||||
}
|
||||
virtual void ResizeBuffers()
|
||||
{
|
||||
m_register.New(m_cipher->BlockSize());
|
||||
}
|
||||
virtual void UncheckedSetKey(const NameValuePairs ¶ms, const byte *key, unsigned int length) =0;
|
||||
|
||||
BlockCipher *m_cipher;
|
||||
SecByteBlock m_register;
|
||||
};
|
||||
|
||||
template <class POLICY_INTERFACE>
|
||||
class ModePolicyCommonTemplate : public CipherModeBase, public POLICY_INTERFACE
|
||||
{
|
||||
unsigned int GetAlignment() const {return m_cipher->BlockAlignment();}
|
||||
void CipherSetKey(const NameValuePairs ¶ms, const byte *key, unsigned int length)
|
||||
{
|
||||
m_cipher->SetKey(key, length, params);
|
||||
ResizeBuffers();
|
||||
int feedbackSize = params.GetIntValueWithDefault(Name::FeedbackSize(), 0);
|
||||
SetFeedbackSize(feedbackSize);
|
||||
const byte *iv = params.GetValueWithDefault(Name::IV(), (const byte *)NULL);
|
||||
SetIV(iv);
|
||||
}
|
||||
};
|
||||
|
||||
class CFB_ModePolicy : public ModePolicyCommonTemplate<CFB_CipherAbstractPolicy>
|
||||
{
|
||||
public:
|
||||
IV_Requirement IVRequirement() const {return RANDOM_IV;}
|
||||
|
||||
protected:
|
||||
unsigned int GetBytesPerIteration() const {return m_feedbackSize;}
|
||||
byte * GetRegisterBegin() {return m_register + BlockSize() - m_feedbackSize;}
|
||||
void TransformRegister()
|
||||
{
|
||||
m_cipher->ProcessBlock(m_register, m_temp);
|
||||
memmove(m_register, m_register+m_feedbackSize, BlockSize()-m_feedbackSize);
|
||||
memcpy(m_register+BlockSize()-m_feedbackSize, m_temp, m_feedbackSize);
|
||||
}
|
||||
void CipherResynchronize(const byte *iv)
|
||||
{
|
||||
memcpy(m_register, iv, BlockSize());
|
||||
TransformRegister();
|
||||
}
|
||||
void SetFeedbackSize(unsigned int feedbackSize)
|
||||
{
|
||||
if (feedbackSize > BlockSize())
|
||||
throw InvalidArgument("CFB_Mode: invalid feedback size");
|
||||
m_feedbackSize = feedbackSize ? feedbackSize : BlockSize();
|
||||
}
|
||||
void ResizeBuffers()
|
||||
{
|
||||
CipherModeBase::ResizeBuffers();
|
||||
m_temp.New(BlockSize());
|
||||
}
|
||||
|
||||
SecByteBlock m_temp;
|
||||
unsigned int m_feedbackSize;
|
||||
};
|
||||
|
||||
class OFB_ModePolicy : public ModePolicyCommonTemplate<AdditiveCipherAbstractPolicy>
|
||||
{
|
||||
unsigned int GetBytesPerIteration() const {return BlockSize();}
|
||||
unsigned int GetIterationsToBuffer() const {return 1;}
|
||||
void WriteKeystream(byte *keystreamBuffer, unsigned int iterationCount)
|
||||
{
|
||||
assert(iterationCount == 1);
|
||||
m_cipher->ProcessBlock(keystreamBuffer);
|
||||
}
|
||||
void CipherResynchronize(byte *keystreamBuffer, const byte *iv)
|
||||
{
|
||||
memcpy(keystreamBuffer, iv, BlockSize());
|
||||
}
|
||||
bool IsRandomAccess() const {return false;}
|
||||
IV_Requirement IVRequirement() const {return STRUCTURED_IV;}
|
||||
};
|
||||
|
||||
class CTR_ModePolicy : public ModePolicyCommonTemplate<AdditiveCipherAbstractPolicy>
|
||||
{
|
||||
unsigned int GetBytesPerIteration() const {return BlockSize();}
|
||||
unsigned int GetIterationsToBuffer() const {return m_cipher->OptimalNumberOfParallelBlocks();}
|
||||
void WriteKeystream(byte *buffer, unsigned int iterationCount)
|
||||
{OperateKeystream(WRITE_KEYSTREAM, buffer, NULL, iterationCount);}
|
||||
bool CanOperateKeystream() const {return true;}
|
||||
void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, unsigned int iterationCount);
|
||||
void CipherResynchronize(byte *keystreamBuffer, const byte *iv);
|
||||
bool IsRandomAccess() const {return true;}
|
||||
void SeekToIteration(dword iterationCount);
|
||||
IV_Requirement IVRequirement() const {return STRUCTURED_IV;}
|
||||
|
||||
inline void ProcessMultipleBlocks(byte *output, const byte *input, unsigned int n);
|
||||
|
||||
SecByteBlock m_counterArray;
|
||||
};
|
||||
|
||||
class BlockOrientedCipherModeBase : public CipherModeBase
|
||||
{
|
||||
public:
|
||||
void UncheckedSetKey(const NameValuePairs ¶ms, const byte *key, unsigned int length);
|
||||
unsigned int MandatoryBlockSize() const {return BlockSize();}
|
||||
bool IsRandomAccess() const {return false;}
|
||||
bool IsSelfInverting() const {return false;}
|
||||
bool IsForwardTransformation() const {return m_cipher->IsForwardTransformation();}
|
||||
void Resynchronize(const byte *iv) {memcpy(m_register, iv, BlockSize());}
|
||||
void ProcessData(byte *outString, const byte *inString, unsigned int length);
|
||||
|
||||
protected:
|
||||
bool RequireAlignedInput() const {return true;}
|
||||
virtual void ProcessBlocks(byte *outString, const byte *inString, unsigned int numberOfBlocks) =0;
|
||||
void ResizeBuffers()
|
||||
{
|
||||
CipherModeBase::ResizeBuffers();
|
||||
m_buffer.New(BlockSize());
|
||||
}
|
||||
|
||||
SecByteBlock m_buffer;
|
||||
};
|
||||
|
||||
class ECB_OneWay : public BlockOrientedCipherModeBase
|
||||
{
|
||||
public:
|
||||
IV_Requirement IVRequirement() const {return NOT_RESYNCHRONIZABLE;}
|
||||
unsigned int OptimalBlockSize() const {return BlockSize() * m_cipher->OptimalNumberOfParallelBlocks();}
|
||||
void ProcessBlocks(byte *outString, const byte *inString, unsigned int numberOfBlocks)
|
||||
{m_cipher->ProcessAndXorMultipleBlocks(inString, NULL, outString, numberOfBlocks);}
|
||||
};
|
||||
|
||||
class CBC_ModeBase : public BlockOrientedCipherModeBase
|
||||
{
|
||||
public:
|
||||
IV_Requirement IVRequirement() const {return UNPREDICTABLE_RANDOM_IV;}
|
||||
bool RequireAlignedInput() const {return false;}
|
||||
unsigned int MinLastBlockSize() const {return 0;}
|
||||
};
|
||||
|
||||
class CBC_Encryption : public CBC_ModeBase
|
||||
{
|
||||
public:
|
||||
void ProcessBlocks(byte *outString, const byte *inString, unsigned int numberOfBlocks);
|
||||
};
|
||||
|
||||
class CBC_CTS_Encryption : public CBC_Encryption
|
||||
{
|
||||
public:
|
||||
void SetStolenIV(byte *iv) {m_stolenIV = iv;}
|
||||
unsigned int MinLastBlockSize() const {return BlockSize()+1;}
|
||||
void ProcessLastBlock(byte *outString, const byte *inString, unsigned int length);
|
||||
|
||||
protected:
|
||||
void UncheckedSetKey(const NameValuePairs ¶ms, const byte *key, unsigned int length)
|
||||
{
|
||||
CBC_Encryption::UncheckedSetKey(params, key, length);
|
||||
m_stolenIV = params.GetValueWithDefault(Name::StolenIV(), (byte *)NULL);
|
||||
}
|
||||
|
||||
byte *m_stolenIV;
|
||||
};
|
||||
|
||||
class CBC_Decryption : public CBC_ModeBase
|
||||
{
|
||||
public:
|
||||
void ProcessBlocks(byte *outString, const byte *inString, unsigned int numberOfBlocks);
|
||||
|
||||
protected:
|
||||
void ResizeBuffers()
|
||||
{
|
||||
BlockOrientedCipherModeBase::ResizeBuffers();
|
||||
m_temp.New(BlockSize());
|
||||
}
|
||||
SecByteBlock m_temp;
|
||||
};
|
||||
|
||||
class CBC_CTS_Decryption : public CBC_Decryption
|
||||
{
|
||||
public:
|
||||
unsigned int MinLastBlockSize() const {return BlockSize()+1;}
|
||||
void ProcessLastBlock(byte *outString, const byte *inString, unsigned int length);
|
||||
};
|
||||
|
||||
//! .
|
||||
template <class CIPHER, class BASE>
|
||||
class CipherModeFinalTemplate_CipherHolder : public ObjectHolder<CIPHER>, public BASE
|
||||
{
|
||||
public:
|
||||
CipherModeFinalTemplate_CipherHolder()
|
||||
{
|
||||
m_cipher = &m_object;
|
||||
ResizeBuffers();
|
||||
}
|
||||
CipherModeFinalTemplate_CipherHolder(const byte *key, unsigned int length)
|
||||
{
|
||||
m_cipher = &m_object;
|
||||
SetKey(key, length);
|
||||
}
|
||||
CipherModeFinalTemplate_CipherHolder(const byte *key, unsigned int length, const byte *iv, int feedbackSize = 0)
|
||||
{
|
||||
m_cipher = &m_object;
|
||||
SetKey(key, length, MakeParameters("IV", iv)("FeedbackSize", feedbackSize));
|
||||
}
|
||||
};
|
||||
|
||||
//! .
|
||||
template <class BASE>
|
||||
class CipherModeFinalTemplate_ExternalCipher : public BASE
|
||||
{
|
||||
public:
|
||||
CipherModeFinalTemplate_ExternalCipher(BlockCipher &cipher, const byte *iv = NULL, int feedbackSize = 0)
|
||||
{
|
||||
m_cipher = &cipher;
|
||||
ResizeBuffers();
|
||||
SetFeedbackSize(feedbackSize);
|
||||
SetIV(iv);
|
||||
}
|
||||
};
|
||||
|
||||
//! CFB mode
|
||||
template <class CIPHER>
|
||||
struct CFB_Mode : public CipherModeDocumentation
|
||||
{
|
||||
typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > Encryption;
|
||||
typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > Decryption;
|
||||
};
|
||||
|
||||
//! CFB mode, external cipher
|
||||
struct CFB_Mode_ExternalCipher : public CipherModeDocumentation
|
||||
{
|
||||
typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > Encryption;
|
||||
typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > Decryption;
|
||||
};
|
||||
|
||||
//! OFB mode
|
||||
template <class CIPHER>
|
||||
struct OFB_Mode : public CipherModeDocumentation
|
||||
{
|
||||
typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, OFB_ModePolicy> > > > Encryption;
|
||||
typedef Encryption Decryption;
|
||||
};
|
||||
|
||||
//! OFB mode, external cipher
|
||||
struct OFB_Mode_ExternalCipher : public CipherModeDocumentation
|
||||
{
|
||||
typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, OFB_ModePolicy> > > > Encryption;
|
||||
typedef Encryption Decryption;
|
||||
};
|
||||
|
||||
//! CTR mode
|
||||
template <class CIPHER>
|
||||
struct CTR_Mode : public CipherModeDocumentation
|
||||
{
|
||||
typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, CTR_ModePolicy> > > > Encryption;
|
||||
typedef Encryption Decryption;
|
||||
};
|
||||
|
||||
//! CTR mode, external cipher
|
||||
struct CTR_Mode_ExternalCipher : public CipherModeDocumentation
|
||||
{
|
||||
typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, CTR_ModePolicy> > > > Encryption;
|
||||
typedef Encryption Decryption;
|
||||
};
|
||||
|
||||
//! ECB mode
|
||||
template <class CIPHER>
|
||||
struct ECB_Mode : public CipherModeDocumentation
|
||||
{
|
||||
typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ECB_OneWay> Encryption;
|
||||
typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Decryption, ECB_OneWay> Decryption;
|
||||
};
|
||||
|
||||
//! ECB mode, external cipher
|
||||
struct ECB_Mode_ExternalCipher : public CipherModeDocumentation
|
||||
{
|
||||
typedef CipherModeFinalTemplate_ExternalCipher<ECB_OneWay> Encryption;
|
||||
typedef Encryption Decryption;
|
||||
};
|
||||
|
||||
//! CBC mode
|
||||
template <class CIPHER>
|
||||
struct CBC_Mode : public CipherModeDocumentation
|
||||
{
|
||||
typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, CBC_Encryption> Encryption;
|
||||
typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Decryption, CBC_Decryption> Decryption;
|
||||
};
|
||||
|
||||
//! CBC mode, external cipher
|
||||
struct CBC_Mode_ExternalCipher : public CipherModeDocumentation
|
||||
{
|
||||
typedef CipherModeFinalTemplate_ExternalCipher<CBC_Encryption> Encryption;
|
||||
typedef CipherModeFinalTemplate_ExternalCipher<CBC_Decryption> Decryption;
|
||||
};
|
||||
|
||||
//! CBC mode with ciphertext stealing
|
||||
template <class CIPHER>
|
||||
struct CBC_CTS_Mode : public CipherModeDocumentation
|
||||
{
|
||||
typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, CBC_CTS_Encryption> Encryption;
|
||||
typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Decryption, CBC_CTS_Decryption> Decryption;
|
||||
};
|
||||
|
||||
//! CBC mode with ciphertext stealing, external cipher
|
||||
struct CBC_CTS_Mode_ExternalCipher : public CipherModeDocumentation
|
||||
{
|
||||
typedef CipherModeFinalTemplate_ExternalCipher<CBC_CTS_Encryption> Encryption;
|
||||
typedef CipherModeFinalTemplate_ExternalCipher<CBC_CTS_Decryption> Decryption;
|
||||
};
|
||||
|
||||
#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
|
||||
typedef CFB_Mode_ExternalCipher::Encryption CFBEncryption;
|
||||
typedef CFB_Mode_ExternalCipher::Decryption CFBDecryption;
|
||||
typedef OFB_Mode_ExternalCipher::Encryption OFB;
|
||||
typedef CTR_Mode_ExternalCipher::Encryption CounterMode;
|
||||
#endif
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,182 @@
|
||||
// mqueue.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
#include "mqueue.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
MessageQueue::MessageQueue(unsigned int nodeSize)
|
||||
: m_queue(nodeSize), m_lengths(1, 0U), m_messageCounts(1, 0U)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned int MessageQueue::CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end, const std::string &channel, bool blocking) const
|
||||
{
|
||||
if (begin >= MaxRetrievable())
|
||||
return 0;
|
||||
|
||||
return m_queue.CopyRangeTo2(target, begin, STDMIN(MaxRetrievable(), end), channel, blocking);
|
||||
}
|
||||
|
||||
unsigned int MessageQueue::TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel, bool blocking)
|
||||
{
|
||||
transferBytes = STDMIN(MaxRetrievable(), transferBytes);
|
||||
unsigned int blockedBytes = m_queue.TransferTo2(target, transferBytes, channel, blocking);
|
||||
m_lengths.front() -= transferBytes;
|
||||
return blockedBytes;
|
||||
}
|
||||
|
||||
bool MessageQueue::GetNextMessage()
|
||||
{
|
||||
if (NumberOfMessages() > 0 && !AnyRetrievable())
|
||||
{
|
||||
m_lengths.pop_front();
|
||||
if (m_messageCounts[0] == 0 && m_messageCounts.size() > 1)
|
||||
m_messageCounts.pop_front();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int MessageQueue::CopyMessagesTo(BufferedTransformation &target, unsigned int count, const std::string &channel) 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, channel);
|
||||
if (GetAutoSignalPropagation())
|
||||
target.ChannelMessageEnd(channel, GetAutoSignalPropagation()-1);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
void MessageQueue::swap(MessageQueue &rhs)
|
||||
{
|
||||
m_queue.swap(rhs.m_queue);
|
||||
m_lengths.swap(rhs.m_lengths);
|
||||
}
|
||||
|
||||
const byte * MessageQueue::Spy(unsigned int &contiguousSize) const
|
||||
{
|
||||
const byte *result = m_queue.Spy(contiguousSize);
|
||||
contiguousSize = (unsigned int)STDMIN((unsigned long)contiguousSize, MaxRetrievable());
|
||||
return result;
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
|
||||
unsigned int EqualityComparisonFilter::MapChannel(const std::string &channel) const
|
||||
{
|
||||
if (channel == m_firstChannel)
|
||||
return 0;
|
||||
else if (channel == m_secondChannel)
|
||||
return 1;
|
||||
else
|
||||
return 2;
|
||||
}
|
||||
|
||||
unsigned int EqualityComparisonFilter::ChannelPut2(const std::string &channel, const byte *inString, unsigned int length, int messageEnd, bool blocking)
|
||||
{
|
||||
if (!blocking)
|
||||
throw BlockingInputOnly("EqualityComparisonFilter");
|
||||
|
||||
unsigned int i = MapChannel(channel);
|
||||
|
||||
if (i == 2)
|
||||
return Output(3, inString, length, messageEnd, blocking, channel);
|
||||
else if (m_mismatchDetected)
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
MessageQueue &q1 = m_q[i], &q2 = m_q[1-i];
|
||||
|
||||
if (q2.AnyMessages() && q2.MaxRetrievable() < length)
|
||||
goto mismatch;
|
||||
|
||||
while (length > 0 && q2.AnyRetrievable())
|
||||
{
|
||||
unsigned int len = length;
|
||||
const byte *data = q2.Spy(len);
|
||||
len = STDMIN(len, length);
|
||||
if (memcmp(inString, data, len) != 0)
|
||||
goto mismatch;
|
||||
inString += len;
|
||||
length -= len;
|
||||
q2.Skip(len);
|
||||
}
|
||||
|
||||
q1.Put(inString, length);
|
||||
|
||||
if (messageEnd)
|
||||
{
|
||||
if (q2.AnyRetrievable())
|
||||
goto mismatch;
|
||||
else if (q2.AnyMessages())
|
||||
q2.GetNextMessage();
|
||||
else if (q2.NumberOfMessageSeries() > 0)
|
||||
goto mismatch;
|
||||
else
|
||||
q1.MessageEnd();
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
mismatch:
|
||||
return HandleMismatchDetected(blocking);
|
||||
}
|
||||
}
|
||||
|
||||
void EqualityComparisonFilter::ChannelInitialize(const std::string &channel, const NameValuePairs ¶meters, int propagation)
|
||||
{
|
||||
unsigned int i = MapChannel(channel);
|
||||
|
||||
if (i == 2)
|
||||
PropagateInitialize(parameters, propagation, channel);
|
||||
else
|
||||
{
|
||||
m_q[i].Initialize();
|
||||
m_mismatchDetected = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool EqualityComparisonFilter::ChannelMessageSeriesEnd(const std::string &channel, int propagation, bool blocking)
|
||||
{
|
||||
unsigned int i = MapChannel(channel);
|
||||
|
||||
if (i == 2)
|
||||
{
|
||||
OutputMessageSeriesEnd(4, propagation, blocking, channel);
|
||||
return false;
|
||||
}
|
||||
else if (m_mismatchDetected)
|
||||
return false;
|
||||
else
|
||||
{
|
||||
MessageQueue &q1 = m_q[i], &q2 = m_q[1-i];
|
||||
|
||||
if (q2.AnyRetrievable() || q2.AnyMessages())
|
||||
goto mismatch;
|
||||
else if (q2.NumberOfMessageSeries() > 0)
|
||||
return Output(2, (const byte *)"\1", 1, 0, blocking) != 0;
|
||||
else
|
||||
q1.MessageSeriesEnd();
|
||||
|
||||
return false;
|
||||
|
||||
mismatch:
|
||||
return HandleMismatchDetected(blocking);
|
||||
}
|
||||
}
|
||||
|
||||
bool EqualityComparisonFilter::HandleMismatchDetected(bool blocking)
|
||||
{
|
||||
m_mismatchDetected = true;
|
||||
if (m_throwIfNotEqual)
|
||||
throw MismatchDetected();
|
||||
return Output(1, (const byte *)"\0", 1, 0, blocking) != 0;
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -0,0 +1,98 @@
|
||||
#ifndef CRYPTOPP_MQUEUE_H
|
||||
#define CRYPTOPP_MQUEUE_H
|
||||
|
||||
#include "queue.h"
|
||||
#include "filters.h"
|
||||
#include <deque>
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
//! Message Queue
|
||||
class MessageQueue : public AutoSignaling<BufferedTransformation>
|
||||
{
|
||||
public:
|
||||
MessageQueue(unsigned int nodeSize=256);
|
||||
|
||||
void IsolatedInitialize(const NameValuePairs ¶meters)
|
||||
{m_queue.IsolatedInitialize(parameters); m_lengths.assign(1, 0U); m_messageCounts.assign(1, 0U);}
|
||||
unsigned int Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking)
|
||||
{
|
||||
m_queue.Put(begin, length);
|
||||
m_lengths.back() += length;
|
||||
if (messageEnd)
|
||||
{
|
||||
m_lengths.push_back(0);
|
||||
m_messageCounts.back()++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
bool IsolatedFlush(bool hardFlush, bool blocking) {return false;}
|
||||
bool IsolatedMessageSeriesEnd(bool blocking)
|
||||
{m_messageCounts.push_back(0); return false;}
|
||||
|
||||
unsigned long MaxRetrievable() const
|
||||
{return m_lengths.front();}
|
||||
bool AnyRetrievable() const
|
||||
{return m_lengths.front() > 0;}
|
||||
|
||||
unsigned int TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel=NULL_CHANNEL, bool blocking=true);
|
||||
unsigned int CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end=ULONG_MAX, const std::string &channel=NULL_CHANNEL, bool blocking=true) const;
|
||||
|
||||
unsigned long TotalBytesRetrievable() const
|
||||
{return m_queue.MaxRetrievable();}
|
||||
unsigned int NumberOfMessages() const
|
||||
{return m_lengths.size()-1;}
|
||||
bool GetNextMessage();
|
||||
|
||||
unsigned int NumberOfMessagesInThisSeries() const
|
||||
{return m_messageCounts[0];}
|
||||
unsigned int NumberOfMessageSeries() const
|
||||
{return m_messageCounts.size()-1;}
|
||||
|
||||
unsigned int CopyMessagesTo(BufferedTransformation &target, unsigned int count=UINT_MAX, const std::string &channel=NULL_CHANNEL) const;
|
||||
|
||||
const byte * Spy(unsigned int &contiguousSize) const;
|
||||
|
||||
void swap(MessageQueue &rhs);
|
||||
|
||||
private:
|
||||
ByteQueue m_queue;
|
||||
std::deque<unsigned long> m_lengths, m_messageCounts;
|
||||
};
|
||||
|
||||
|
||||
//! A filter that checks messages on two channels for equality
|
||||
class EqualityComparisonFilter : public Unflushable<Multichannel<Filter> >
|
||||
{
|
||||
public:
|
||||
struct MismatchDetected : public Exception {MismatchDetected() : Exception(DATA_INTEGRITY_CHECK_FAILED, "EqualityComparisonFilter: did not receive the same data on two channels") {}};
|
||||
|
||||
/*! if throwIfNotEqual is false, this filter will output a '\0' byte when it detects a mismatch, '\1' otherwise */
|
||||
EqualityComparisonFilter(BufferedTransformation *attachment=NULL, bool throwIfNotEqual=true, const std::string &firstChannel="0", const std::string &secondChannel="1")
|
||||
: Unflushable<Multichannel<Filter> >(attachment), m_throwIfNotEqual(throwIfNotEqual), m_mismatchDetected(false)
|
||||
, m_firstChannel(firstChannel), m_secondChannel(secondChannel) {}
|
||||
|
||||
unsigned int ChannelPut2(const std::string &channel, const byte *begin, unsigned int length, int messageEnd, bool blocking);
|
||||
|
||||
void ChannelInitialize(const std::string &channel, const NameValuePairs ¶meters=g_nullNameValuePairs, int propagation=-1);
|
||||
bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true);
|
||||
|
||||
private:
|
||||
unsigned int MapChannel(const std::string &channel) const;
|
||||
bool HandleMismatchDetected(bool blocking);
|
||||
|
||||
bool m_throwIfNotEqual, m_mismatchDetected;
|
||||
std::string m_firstChannel, m_secondChannel;
|
||||
MessageQueue m_q[2];
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
NAMESPACE_BEGIN(std)
|
||||
template<> inline void swap(CryptoPP::MessageQueue &a, CryptoPP::MessageQueue &b)
|
||||
{
|
||||
a.swap(b);
|
||||
}
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,143 @@
|
||||
// nbtheory.h - written and placed in the public domain by Wei Dai
|
||||
|
||||
#ifndef CRYPTOPP_NBTHEORY_H
|
||||
#define CRYPTOPP_NBTHEORY_H
|
||||
|
||||
#include "integer.h"
|
||||
#include "algparam.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
// export a table of small primes
|
||||
extern const unsigned int maxPrimeTableSize;
|
||||
extern const word lastSmallPrime;
|
||||
extern unsigned int primeTableSize;
|
||||
extern word primeTable[];
|
||||
|
||||
// build up the table to maxPrimeTableSize
|
||||
void BuildPrimeTable();
|
||||
|
||||
// ************ primality testing ****************
|
||||
|
||||
// generate a provable prime
|
||||
Integer MaurerProvablePrime(RandomNumberGenerator &rng, unsigned int bits);
|
||||
Integer MihailescuProvablePrime(RandomNumberGenerator &rng, unsigned int bits);
|
||||
|
||||
bool IsSmallPrime(const Integer &p);
|
||||
|
||||
// returns true if p is divisible by some prime less than bound
|
||||
// bound not be greater than the largest entry in the prime table
|
||||
bool TrialDivision(const Integer &p, unsigned bound);
|
||||
|
||||
// returns true if p is NOT divisible by small primes
|
||||
bool SmallDivisorsTest(const Integer &p);
|
||||
|
||||
// These is no reason to use these two, use the ones below instead
|
||||
bool IsFermatProbablePrime(const Integer &n, const Integer &b);
|
||||
bool IsLucasProbablePrime(const Integer &n);
|
||||
|
||||
bool IsStrongProbablePrime(const Integer &n, const Integer &b);
|
||||
bool IsStrongLucasProbablePrime(const Integer &n);
|
||||
|
||||
// Rabin-Miller primality test, i.e. repeating the strong probable prime test
|
||||
// for several rounds with random bases
|
||||
bool RabinMillerTest(RandomNumberGenerator &rng, const Integer &w, unsigned int rounds);
|
||||
|
||||
// primality test, used to generate primes
|
||||
bool IsPrime(const Integer &p);
|
||||
|
||||
// more reliable than IsPrime(), used to verify primes generated by others
|
||||
bool VerifyPrime(RandomNumberGenerator &rng, const Integer &p, unsigned int level = 1);
|
||||
|
||||
class PrimeSelector
|
||||
{
|
||||
public:
|
||||
const PrimeSelector *GetSelectorPointer() const {return this;}
|
||||
virtual bool IsAcceptable(const Integer &candidate) const =0;
|
||||
};
|
||||
|
||||
// use a fast sieve to find the first probable prime in {x | p<=x<=max and x%mod==equiv}
|
||||
// returns true iff successful, value of p is undefined if no such prime exists
|
||||
bool FirstPrime(Integer &p, const Integer &max, const Integer &equiv, const Integer &mod, const PrimeSelector *pSelector);
|
||||
|
||||
unsigned int PrimeSearchInterval(const Integer &max);
|
||||
|
||||
AlgorithmParameters<AlgorithmParameters<AlgorithmParameters<NullNameValuePairs, Integer::RandomNumberType>, Integer>, Integer>
|
||||
MakeParametersForTwoPrimesOfEqualSize(unsigned int productBitLength);
|
||||
|
||||
// ********** other number theoretic functions ************
|
||||
|
||||
inline Integer GCD(const Integer &a, const Integer &b)
|
||||
{return Integer::Gcd(a,b);}
|
||||
inline bool RelativelyPrime(const Integer &a, const Integer &b)
|
||||
{return Integer::Gcd(a,b) == Integer::One();}
|
||||
inline Integer LCM(const Integer &a, const Integer &b)
|
||||
{return a/Integer::Gcd(a,b)*b;}
|
||||
inline Integer EuclideanMultiplicativeInverse(const Integer &a, const Integer &b)
|
||||
{return a.InverseMod(b);}
|
||||
|
||||
// use Chinese Remainder Theorem to calculate x given x mod p and x mod q
|
||||
Integer CRT(const Integer &xp, const Integer &p, const Integer &xq, const Integer &q);
|
||||
// use this one if u = inverse of p mod q has been precalculated
|
||||
Integer CRT(const Integer &xp, const Integer &p, const Integer &xq, const Integer &q, const Integer &u);
|
||||
|
||||
// if b is prime, then Jacobi(a, b) returns 0 if a%b==0, 1 if a is quadratic residue mod b, -1 otherwise
|
||||
// check a number theory book for what Jacobi symbol means when b is not prime
|
||||
int Jacobi(const Integer &a, const Integer &b);
|
||||
|
||||
// calculates the Lucas function V_e(p, 1) mod n
|
||||
Integer Lucas(const Integer &e, const Integer &p, const Integer &n);
|
||||
// calculates x such that m==Lucas(e, x, p*q), p q primes
|
||||
Integer InverseLucas(const Integer &e, const Integer &m, const Integer &p, const Integer &q);
|
||||
// use this one if u=inverse of p mod q has been precalculated
|
||||
Integer InverseLucas(const Integer &e, const Integer &m, const Integer &p, const Integer &q, const Integer &u);
|
||||
|
||||
inline Integer ModularExponentiation(const Integer &a, const Integer &e, const Integer &m)
|
||||
{return a_exp_b_mod_c(a, e, m);}
|
||||
// returns x such that x*x%p == a, p prime
|
||||
Integer ModularSquareRoot(const Integer &a, const Integer &p);
|
||||
// returns x such that a==ModularExponentiation(x, e, p*q), p q primes,
|
||||
// and e relatively prime to (p-1)*(q-1)
|
||||
Integer ModularRoot(const Integer &a, const Integer &e, const Integer &p, const Integer &q);
|
||||
// use this one if dp=d%(p-1), dq=d%(q-1), (d is inverse of e mod (p-1)*(q-1))
|
||||
// and u=inverse of p mod q have been precalculated
|
||||
Integer ModularRoot(const Integer &a, const Integer &dp, const Integer &dq, const Integer &p, const Integer &q, const Integer &u);
|
||||
|
||||
// find r1 and r2 such that ax^2 + bx + c == 0 (mod p) for x in {r1, r2}, p prime
|
||||
// returns true if solutions exist
|
||||
bool SolveModularQuadraticEquation(Integer &r1, Integer &r2, const Integer &a, const Integer &b, const Integer &c, const Integer &p);
|
||||
|
||||
// returns log base 2 of estimated number of operations to calculate discrete log or factor a number
|
||||
unsigned int DiscreteLogWorkFactor(unsigned int bitlength);
|
||||
unsigned int FactoringWorkFactor(unsigned int bitlength);
|
||||
|
||||
// ********************************************************
|
||||
|
||||
//! generator of prime numbers of special forms
|
||||
class PrimeAndGenerator
|
||||
{
|
||||
public:
|
||||
PrimeAndGenerator() {}
|
||||
// generate a random prime p of the form 2*q+delta, where delta is 1 or -1 and q is also prime
|
||||
// Precondition: pbits > 5
|
||||
// warning: this is slow, because primes of this form are harder to find
|
||||
PrimeAndGenerator(signed int delta, RandomNumberGenerator &rng, unsigned int pbits)
|
||||
{Generate(delta, rng, pbits, pbits-1);}
|
||||
// generate a random prime p of the form 2*r*q+delta, where q is also prime
|
||||
// Precondition: qbits > 4 && pbits > qbits
|
||||
PrimeAndGenerator(signed int delta, RandomNumberGenerator &rng, unsigned int pbits, unsigned qbits)
|
||||
{Generate(delta, rng, pbits, qbits);}
|
||||
|
||||
void Generate(signed int delta, RandomNumberGenerator &rng, unsigned int pbits, unsigned qbits);
|
||||
|
||||
const Integer& Prime() const {return p;}
|
||||
const Integer& SubPrime() const {return q;}
|
||||
const Integer& Generator() const {return g;}
|
||||
|
||||
private:
|
||||
Integer p, q, g;
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,107 @@
|
||||
// oaep.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
#include "oaep.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
// ********************************************************
|
||||
|
||||
ANONYMOUS_NAMESPACE_BEGIN
|
||||
template <class H, byte *P, unsigned int PLen>
|
||||
struct PHashComputation
|
||||
{
|
||||
PHashComputation() {H().CalculateDigest(pHash, P, PLen);}
|
||||
byte pHash[H::DIGESTSIZE];
|
||||
};
|
||||
|
||||
template <class H, byte *P, unsigned int PLen>
|
||||
const byte *PHash()
|
||||
{
|
||||
static PHashComputation<H,P,PLen> pHash;
|
||||
return pHash.pHash;
|
||||
}
|
||||
NAMESPACE_END
|
||||
|
||||
template <class H, class MGF, byte *P, unsigned int PLen>
|
||||
unsigned int OAEP<H,MGF,P,PLen>::MaxUnpaddedLength(unsigned int paddedLength) const
|
||||
{
|
||||
return paddedLength/8 > 1+2*H::DIGESTSIZE ? paddedLength/8-1-2*H::DIGESTSIZE : 0;
|
||||
}
|
||||
|
||||
template <class H, class MGF, byte *P, unsigned int PLen>
|
||||
void OAEP<H,MGF,P,PLen>::Pad(RandomNumberGenerator &rng, const byte *input, unsigned int inputLength, byte *oaepBlock, unsigned int oaepBlockLen) const
|
||||
{
|
||||
assert (inputLength <= MaxUnpaddedLength(oaepBlockLen));
|
||||
|
||||
// convert from bit length to byte length
|
||||
if (oaepBlockLen % 8 != 0)
|
||||
{
|
||||
oaepBlock[0] = 0;
|
||||
oaepBlock++;
|
||||
}
|
||||
oaepBlockLen /= 8;
|
||||
|
||||
const unsigned int hLen = H::DIGESTSIZE;
|
||||
const unsigned int seedLen = hLen, dbLen = oaepBlockLen-seedLen;
|
||||
byte *const maskedSeed = oaepBlock;
|
||||
byte *const maskedDB = oaepBlock+seedLen;
|
||||
|
||||
// DB = pHash || 00 ... || 01 || M
|
||||
memcpy(maskedDB, PHash<H,P,PLen>(), hLen);
|
||||
memset(maskedDB+hLen, 0, dbLen-hLen-inputLength-1);
|
||||
maskedDB[dbLen-inputLength-1] = 0x01;
|
||||
memcpy(maskedDB+dbLen-inputLength, input, inputLength);
|
||||
|
||||
rng.GenerateBlock(maskedSeed, seedLen);
|
||||
H h;
|
||||
MGF mgf;
|
||||
mgf.GenerateAndMask(h, maskedDB, dbLen, maskedSeed, seedLen);
|
||||
mgf.GenerateAndMask(h, maskedSeed, seedLen, maskedDB, dbLen);
|
||||
}
|
||||
|
||||
template <class H, class MGF, byte *P, unsigned int PLen>
|
||||
DecodingResult OAEP<H,MGF,P,PLen>::Unpad(const byte *oaepBlock, unsigned int oaepBlockLen, byte *output) const
|
||||
{
|
||||
bool invalid = false;
|
||||
|
||||
// convert from bit length to byte length
|
||||
if (oaepBlockLen % 8 != 0)
|
||||
{
|
||||
invalid = (oaepBlock[0] != 0) || invalid;
|
||||
oaepBlock++;
|
||||
}
|
||||
oaepBlockLen /= 8;
|
||||
|
||||
const unsigned int hLen = H::DIGESTSIZE;
|
||||
const unsigned int seedLen = hLen, dbLen = oaepBlockLen-seedLen;
|
||||
|
||||
invalid = (oaepBlockLen < 2*hLen+1) || invalid;
|
||||
|
||||
SecByteBlock t(oaepBlock, oaepBlockLen);
|
||||
byte *const maskedSeed = t;
|
||||
byte *const maskedDB = t+seedLen;
|
||||
|
||||
H h;
|
||||
MGF mgf;
|
||||
mgf.GenerateAndMask(h, maskedSeed, seedLen, maskedDB, dbLen);
|
||||
mgf.GenerateAndMask(h, maskedDB, dbLen, maskedSeed, seedLen);
|
||||
|
||||
// DB = pHash' || 00 ... || 01 || M
|
||||
|
||||
byte *M = std::find(maskedDB+hLen, maskedDB+dbLen, 0x01);
|
||||
invalid = (M == maskedDB+dbLen) || invalid;
|
||||
invalid = (std::find_if(maskedDB+hLen, M, std::bind2nd(std::not_equal_to<byte>(), 0)) != M) || invalid;
|
||||
invalid = (memcmp(maskedDB, PHash<H,P,PLen>(), hLen) != 0) || invalid;
|
||||
|
||||
if (invalid)
|
||||
return DecodingResult();
|
||||
|
||||
M++;
|
||||
memcpy(output, M, maskedDB+dbLen-M);
|
||||
return DecodingResult(maskedDB+dbLen-M);
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -0,0 +1,25 @@
|
||||
#ifndef CRYPTOPP_OAEP_H
|
||||
#define CRYPTOPP_OAEP_H
|
||||
|
||||
#include "pubkey.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
extern byte OAEP_P_DEFAULT[]; // defined in misc.cpp
|
||||
|
||||
/// <a href="http://www.weidai.com/scan-mirror/ca.html#cem_OAEP-MGF1">EME-OAEP</a>, for use with RSAES
|
||||
template <class H, class MGF=P1363_MGF1, byte *P=OAEP_P_DEFAULT, unsigned int PLen=0>
|
||||
class OAEP : public PK_EncryptionMessageEncodingMethod, public EncryptionStandard
|
||||
{
|
||||
public:
|
||||
static std::string StaticAlgorithmName() {return std::string("OAEP-") + MGF::StaticAlgorithmName() + "(" + H::StaticAlgorithmName() + ")";}
|
||||
typedef OAEP<H, MGF, P, PLen> EncryptionMessageEncodingMethod;
|
||||
|
||||
unsigned int MaxUnpaddedLength(unsigned int paddedLength) const;
|
||||
void Pad(RandomNumberGenerator &rng, const byte *raw, unsigned int inputLength, byte *padded, unsigned int paddedLength) const;
|
||||
DecodingResult Unpad(const byte *padded, unsigned int paddedLength, byte *raw) const;
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,112 @@
|
||||
#ifndef CRYPTOPP_OIDS_H
|
||||
#define CRYPTOPP_OIDS_H
|
||||
|
||||
// crypto-related ASN.1 object identifiers
|
||||
|
||||
#include "asn.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
NAMESPACE_BEGIN(ASN1)
|
||||
|
||||
#define DEFINE_OID(value, name) inline OID name() {return value;}
|
||||
|
||||
DEFINE_OID(1, iso)
|
||||
DEFINE_OID(iso()+2, member_body)
|
||||
DEFINE_OID(member_body()+840, iso_us)
|
||||
DEFINE_OID(iso_us()+10040, ansi_x9_57)
|
||||
DEFINE_OID(ansi_x9_57()+4+1, id_dsa)
|
||||
DEFINE_OID(iso_us()+10045, ansi_x9_62)
|
||||
DEFINE_OID(ansi_x9_62()+1, id_fieldType)
|
||||
DEFINE_OID(id_fieldType()+1, prime_field)
|
||||
DEFINE_OID(id_fieldType()+2, characteristic_two_field)
|
||||
DEFINE_OID(characteristic_two_field()+3, id_characteristic_two_basis)
|
||||
DEFINE_OID(id_characteristic_two_basis()+1, gnBasis)
|
||||
DEFINE_OID(id_characteristic_two_basis()+2, tpBasis)
|
||||
DEFINE_OID(id_characteristic_two_basis()+3, ppBasis)
|
||||
DEFINE_OID(ansi_x9_62()+2, id_publicKeyType)
|
||||
DEFINE_OID(id_publicKeyType()+1, id_ecPublicKey)
|
||||
DEFINE_OID(ansi_x9_62()+3, ansi_x9_62_curves)
|
||||
DEFINE_OID(ansi_x9_62_curves()+1, ansi_x9_62_curves_prime)
|
||||
DEFINE_OID(ansi_x9_62_curves_prime()+1, secp192r1)
|
||||
DEFINE_OID(ansi_x9_62_curves_prime()+7, secp256r1)
|
||||
DEFINE_OID(iso_us()+113549, rsadsi)
|
||||
DEFINE_OID(rsadsi()+1, pkcs)
|
||||
DEFINE_OID(pkcs()+1, pkcs_1)
|
||||
DEFINE_OID(pkcs_1()+1, rsaEncryption);
|
||||
DEFINE_OID(rsadsi()+2, rsadsi_digestAlgorithm)
|
||||
DEFINE_OID(rsadsi_digestAlgorithm()+2, id_md2)
|
||||
DEFINE_OID(rsadsi_digestAlgorithm()+5, id_md5)
|
||||
DEFINE_OID(iso()+3, identified_organization);
|
||||
DEFINE_OID(identified_organization()+14, oiw);
|
||||
DEFINE_OID(oiw()+14, oiw_secsig);
|
||||
DEFINE_OID(oiw_secsig()+2, oiw_secsig_algorithms);
|
||||
DEFINE_OID(oiw_secsig_algorithms()+26, id_sha1);
|
||||
DEFINE_OID(identified_organization()+36, teletrust);
|
||||
DEFINE_OID(teletrust()+3+2+1, id_ripemd160)
|
||||
DEFINE_OID(identified_organization()+132, certicom);
|
||||
DEFINE_OID(certicom()+0, certicom_ellipticCurve);
|
||||
// these are sorted by curve type and then by OID
|
||||
// first curves based on GF(p)
|
||||
DEFINE_OID(certicom_ellipticCurve()+6, secp112r1);
|
||||
DEFINE_OID(certicom_ellipticCurve()+7, secp112r2);
|
||||
DEFINE_OID(certicom_ellipticCurve()+8, secp160r1);
|
||||
DEFINE_OID(certicom_ellipticCurve()+9, secp160k1);
|
||||
DEFINE_OID(certicom_ellipticCurve()+10, secp256k1);
|
||||
DEFINE_OID(certicom_ellipticCurve()+28, secp128r1);
|
||||
DEFINE_OID(certicom_ellipticCurve()+29, secp128r2);
|
||||
DEFINE_OID(certicom_ellipticCurve()+30, secp160r2);
|
||||
DEFINE_OID(certicom_ellipticCurve()+31, secp192k1);
|
||||
DEFINE_OID(certicom_ellipticCurve()+32, secp224k1);
|
||||
DEFINE_OID(certicom_ellipticCurve()+33, secp224r1);
|
||||
DEFINE_OID(certicom_ellipticCurve()+34, secp384r1);
|
||||
DEFINE_OID(certicom_ellipticCurve()+35, secp521r1);
|
||||
// then curves based on GF(2^n)
|
||||
DEFINE_OID(certicom_ellipticCurve()+1, sect163k1);
|
||||
DEFINE_OID(certicom_ellipticCurve()+2, sect163r1);
|
||||
DEFINE_OID(certicom_ellipticCurve()+3, sect239k1);
|
||||
DEFINE_OID(certicom_ellipticCurve()+4, sect113r1);
|
||||
DEFINE_OID(certicom_ellipticCurve()+5, sect113r2);
|
||||
DEFINE_OID(certicom_ellipticCurve()+15, sect163r2);
|
||||
DEFINE_OID(certicom_ellipticCurve()+16, sect283k1);
|
||||
DEFINE_OID(certicom_ellipticCurve()+17, sect283r1);
|
||||
DEFINE_OID(certicom_ellipticCurve()+22, sect131r1);
|
||||
DEFINE_OID(certicom_ellipticCurve()+23, sect131r2);
|
||||
DEFINE_OID(certicom_ellipticCurve()+24, sect193r1);
|
||||
DEFINE_OID(certicom_ellipticCurve()+25, sect193r2);
|
||||
DEFINE_OID(certicom_ellipticCurve()+26, sect233k1);
|
||||
DEFINE_OID(certicom_ellipticCurve()+27, sect233r1);
|
||||
DEFINE_OID(certicom_ellipticCurve()+36, sect409k1);
|
||||
DEFINE_OID(certicom_ellipticCurve()+37, sect409r1);
|
||||
DEFINE_OID(certicom_ellipticCurve()+38, sect571k1);
|
||||
DEFINE_OID(certicom_ellipticCurve()+39, sect571r1);
|
||||
DEFINE_OID(2, joint_iso_ccitt)
|
||||
DEFINE_OID(joint_iso_ccitt()+16, country)
|
||||
DEFINE_OID(country()+840, joint_iso_ccitt_us)
|
||||
DEFINE_OID(joint_iso_ccitt_us()+1, us_organization)
|
||||
DEFINE_OID(us_organization()+101, us_gov)
|
||||
DEFINE_OID(us_gov()+3, csor)
|
||||
DEFINE_OID(csor()+4, nistalgorithms)
|
||||
DEFINE_OID(nistalgorithms()+1, aes)
|
||||
DEFINE_OID(aes()+1, id_aes128_ECB)
|
||||
DEFINE_OID(aes()+2, id_aes128_cbc)
|
||||
DEFINE_OID(aes()+3, id_aes128_ofb)
|
||||
DEFINE_OID(aes()+4, id_aes128_cfb)
|
||||
DEFINE_OID(aes()+21, id_aes192_ECB)
|
||||
DEFINE_OID(aes()+22, id_aes192_cbc)
|
||||
DEFINE_OID(aes()+23, id_aes192_ofb)
|
||||
DEFINE_OID(aes()+24, id_aes192_cfb)
|
||||
DEFINE_OID(aes()+41, id_aes256_ECB)
|
||||
DEFINE_OID(aes()+42, id_aes256_cbc)
|
||||
DEFINE_OID(aes()+43, id_aes256_ofb)
|
||||
DEFINE_OID(aes()+44, id_aes256_cfb)
|
||||
DEFINE_OID(nistalgorithms()+2, nist_hashalgs)
|
||||
DEFINE_OID(nist_hashalgs()+1, id_sha256)
|
||||
DEFINE_OID(nist_hashalgs()+2, id_sha384)
|
||||
DEFINE_OID(nist_hashalgs()+3, id_sha512)
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,172 @@
|
||||
// osrng.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
// Thanks to Leonard Janke for the suggestion for AutoSeededRandomPool.
|
||||
|
||||
#include "pch.h"
|
||||
#include "osrng.h"
|
||||
|
||||
#ifdef OS_RNG_AVAILABLE
|
||||
|
||||
#include "rng.h"
|
||||
|
||||
#ifdef CRYPTOPP_WIN32_AVAILABLE
|
||||
#ifndef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x0400
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#include <wincrypt.h>
|
||||
#endif
|
||||
|
||||
#ifdef CRYPTOPP_UNIX_AVAILABLE
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
#if defined(NONBLOCKING_RNG_AVAILABLE) || defined(BLOCKING_RNG_AVAILABLE)
|
||||
OS_RNG_Err::OS_RNG_Err(const std::string &operation)
|
||||
: Exception(OTHER_ERROR, "OS_Rng: " + operation + " operation failed with error " +
|
||||
#ifdef CRYPTOPP_WIN32_AVAILABLE
|
||||
"0x" + IntToString(GetLastError(), 16)
|
||||
#else
|
||||
IntToString(errno)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef NONBLOCKING_RNG_AVAILABLE
|
||||
|
||||
#ifdef CRYPTOPP_WIN32_AVAILABLE
|
||||
|
||||
MicrosoftCryptoProvider::MicrosoftCryptoProvider()
|
||||
{
|
||||
if(!CryptAcquireContext(&m_hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
|
||||
throw OS_RNG_Err("CryptAcquireContext");
|
||||
}
|
||||
|
||||
MicrosoftCryptoProvider::~MicrosoftCryptoProvider()
|
||||
{
|
||||
CryptReleaseContext(m_hProvider, 0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
NonblockingRng::NonblockingRng()
|
||||
{
|
||||
#ifndef CRYPTOPP_WIN32_AVAILABLE
|
||||
m_fd = open("/dev/urandom",O_RDONLY);
|
||||
if (m_fd == -1)
|
||||
throw OS_RNG_Err("open /dev/urandom");
|
||||
#endif
|
||||
}
|
||||
|
||||
NonblockingRng::~NonblockingRng()
|
||||
{
|
||||
#ifndef CRYPTOPP_WIN32_AVAILABLE
|
||||
close(m_fd);
|
||||
#endif
|
||||
}
|
||||
|
||||
byte NonblockingRng::GenerateByte()
|
||||
{
|
||||
byte b;
|
||||
GenerateBlock(&b, 1);
|
||||
return b;
|
||||
}
|
||||
|
||||
void NonblockingRng::GenerateBlock(byte *output, unsigned int size)
|
||||
{
|
||||
#ifdef CRYPTOPP_WIN32_AVAILABLE
|
||||
# ifdef WORKAROUND_MS_BUG_Q258000
|
||||
static MicrosoftCryptoProvider m_Provider;
|
||||
# endif
|
||||
if (!CryptGenRandom(m_Provider.GetProviderHandle(), size, output))
|
||||
throw OS_RNG_Err("CryptGenRandom");
|
||||
#else
|
||||
if (read(m_fd, output, size) != size)
|
||||
throw OS_RNG_Err("read /dev/urandom");
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// *************************************************************
|
||||
|
||||
#ifdef BLOCKING_RNG_AVAILABLE
|
||||
|
||||
BlockingRng::BlockingRng()
|
||||
{
|
||||
m_fd = open("/dev/random",O_RDONLY);
|
||||
if (m_fd == -1)
|
||||
throw OS_RNG_Err("open /dev/random");
|
||||
}
|
||||
|
||||
BlockingRng::~BlockingRng()
|
||||
{
|
||||
close(m_fd);
|
||||
}
|
||||
|
||||
byte BlockingRng::GenerateByte()
|
||||
{
|
||||
byte b;
|
||||
GenerateBlock(&b, 1);
|
||||
return b;
|
||||
}
|
||||
|
||||
void BlockingRng::GenerateBlock(byte *output, unsigned int size)
|
||||
{
|
||||
while (size)
|
||||
{
|
||||
// on some systems /dev/random will block until all bytes
|
||||
// are available, on others it will returns immediately
|
||||
int len = read(m_fd, output, STDMIN(size, (unsigned int)INT_MAX));
|
||||
if (len == -1)
|
||||
throw OS_RNG_Err("read /dev/random");
|
||||
size -= len;
|
||||
output += len;
|
||||
if (size)
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// *************************************************************
|
||||
|
||||
void OS_GenerateRandomBlock(bool blocking, byte *output, unsigned int size)
|
||||
{
|
||||
#ifdef NONBLOCKING_RNG_AVAILABLE
|
||||
if (blocking)
|
||||
#endif
|
||||
{
|
||||
#ifdef BLOCKING_RNG_AVAILABLE
|
||||
BlockingRng rng;
|
||||
rng.GenerateBlock(output, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef BLOCKING_RNG_AVAILABLE
|
||||
if (!blocking)
|
||||
#endif
|
||||
{
|
||||
#ifdef NONBLOCKING_RNG_AVAILABLE
|
||||
NonblockingRng rng;
|
||||
rng.GenerateBlock(output, size);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void AutoSeededRandomPool::Reseed(bool blocking, unsigned int seedSize)
|
||||
{
|
||||
SecByteBlock seed(seedSize);
|
||||
OS_GenerateRandomBlock(blocking, seed, seedSize);
|
||||
Put(seed, seedSize);
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,162 @@
|
||||
#ifndef CRYPTOPP_OSRNG_H
|
||||
#define CRYPTOPP_OSRNG_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef OS_RNG_AVAILABLE
|
||||
|
||||
#include "randpool.h"
|
||||
#include "rng.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
//! Exception class for Operating-System Random Number Generator.
|
||||
class OS_RNG_Err : public Exception
|
||||
{
|
||||
public:
|
||||
OS_RNG_Err(const std::string &operation);
|
||||
};
|
||||
|
||||
#ifdef NONBLOCKING_RNG_AVAILABLE
|
||||
|
||||
#ifdef CRYPTOPP_WIN32_AVAILABLE
|
||||
class MicrosoftCryptoProvider
|
||||
{
|
||||
public:
|
||||
MicrosoftCryptoProvider();
|
||||
~MicrosoftCryptoProvider();
|
||||
#if defined(_WIN64)
|
||||
typedef unsigned __int64 ProviderHandle; // type HCRYPTPROV, avoid #include <windows.h>
|
||||
#else
|
||||
typedef unsigned long ProviderHandle;
|
||||
#endif
|
||||
ProviderHandle GetProviderHandle() const {return m_hProvider;}
|
||||
private:
|
||||
ProviderHandle m_hProvider;
|
||||
};
|
||||
#endif
|
||||
|
||||
//! encapsulate CryptoAPI's CryptGenRandom or /dev/urandom
|
||||
class NonblockingRng : public RandomNumberGenerator
|
||||
{
|
||||
public:
|
||||
NonblockingRng();
|
||||
~NonblockingRng();
|
||||
byte GenerateByte();
|
||||
void GenerateBlock(byte *output, unsigned int size);
|
||||
|
||||
protected:
|
||||
#ifdef CRYPTOPP_WIN32_AVAILABLE
|
||||
# ifndef WORKAROUND_MS_BUG_Q258000
|
||||
MicrosoftCryptoProvider m_Provider;
|
||||
# endif
|
||||
#else
|
||||
int m_fd;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef BLOCKING_RNG_AVAILABLE
|
||||
|
||||
//! encapsulate /dev/random
|
||||
class BlockingRng : public RandomNumberGenerator
|
||||
{
|
||||
public:
|
||||
BlockingRng();
|
||||
~BlockingRng();
|
||||
byte GenerateByte();
|
||||
void GenerateBlock(byte *output, unsigned int size);
|
||||
|
||||
protected:
|
||||
int m_fd;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
void OS_GenerateRandomBlock(bool blocking, byte *output, unsigned int size);
|
||||
|
||||
//! Automaticly Seeded Randomness Pool
|
||||
/*! This class seeds itself using an operating system provided RNG. */
|
||||
class AutoSeededRandomPool : public RandomPool
|
||||
{
|
||||
public:
|
||||
//! blocking will be ignored if the prefered RNG isn't available
|
||||
explicit AutoSeededRandomPool(bool blocking = false, unsigned int seedSize = 32)
|
||||
{Reseed(blocking, seedSize);}
|
||||
void Reseed(bool blocking = false, unsigned int seedSize = 32);
|
||||
};
|
||||
|
||||
//! RNG from ANSI X9.17 Appendix C, seeded using an OS provided RNG
|
||||
template <class BLOCK_CIPHER>
|
||||
class AutoSeededX917RNG : public RandomNumberGenerator
|
||||
{
|
||||
public:
|
||||
//! blocking will be ignored if the prefered RNG isn't available
|
||||
explicit AutoSeededX917RNG(bool blocking = false)
|
||||
{Reseed(blocking);}
|
||||
void Reseed(bool blocking = false);
|
||||
// exposed for testing
|
||||
void Reseed(const byte *key, unsigned int keylength, const byte *seed, unsigned long timeVector);
|
||||
|
||||
byte GenerateByte();
|
||||
|
||||
private:
|
||||
member_ptr<RandomNumberGenerator> m_rng;
|
||||
SecByteBlock m_lastBlock;
|
||||
bool m_isDifferent;
|
||||
unsigned int m_counter;
|
||||
};
|
||||
|
||||
template <class BLOCK_CIPHER>
|
||||
void AutoSeededX917RNG<BLOCK_CIPHER>::Reseed(const byte *key, unsigned int keylength, const byte *seed, unsigned long timeVector)
|
||||
{
|
||||
m_rng.reset(new X917RNG(new typename BLOCK_CIPHER::Encryption(key, keylength), seed, timeVector));
|
||||
|
||||
// for FIPS 140-2
|
||||
m_lastBlock.resize(16);
|
||||
m_rng->GenerateBlock(m_lastBlock, m_lastBlock.size());
|
||||
m_counter = 0;
|
||||
m_isDifferent = false;
|
||||
}
|
||||
|
||||
template <class BLOCK_CIPHER>
|
||||
void AutoSeededX917RNG<BLOCK_CIPHER>::Reseed(bool blocking)
|
||||
{
|
||||
SecByteBlock seed(BLOCK_CIPHER::BLOCKSIZE + BLOCK_CIPHER::DEFAULT_KEYLENGTH);
|
||||
const byte *key;
|
||||
do
|
||||
{
|
||||
OS_GenerateRandomBlock(blocking, seed, seed.size());
|
||||
key = seed + BLOCK_CIPHER::BLOCKSIZE;
|
||||
} // check that seed and key don't have same value
|
||||
while (memcmp(key, seed, STDMIN((unsigned int)BLOCK_CIPHER::BLOCKSIZE, (unsigned int)BLOCK_CIPHER::DEFAULT_KEYLENGTH)) == 0);
|
||||
|
||||
Reseed(key, BLOCK_CIPHER::DEFAULT_KEYLENGTH, seed, 0);
|
||||
}
|
||||
|
||||
template <class BLOCK_CIPHER>
|
||||
byte AutoSeededX917RNG<BLOCK_CIPHER>::GenerateByte()
|
||||
{
|
||||
byte b = m_rng->GenerateByte();
|
||||
|
||||
// for FIPS 140-2
|
||||
m_isDifferent = m_isDifferent || b != m_lastBlock[m_counter];
|
||||
m_lastBlock[m_counter] = b;
|
||||
++m_counter;
|
||||
if (m_counter == m_lastBlock.size())
|
||||
{
|
||||
if (!m_isDifferent)
|
||||
throw SelfTestFailure("AutoSeededX917RNG: Continuous random number generator test failed.");
|
||||
m_counter = 0;
|
||||
m_isDifferent = false;
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,13 @@
|
||||
#ifndef CRYPTOPP_PCH_H
|
||||
#define CRYPTOPP_PCH_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef USE_PRECOMPILED_HEADERS
|
||||
#include "simple.h"
|
||||
#include "secblock.h"
|
||||
#include "misc.h"
|
||||
#include "smartptr.h"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,126 @@
|
||||
// pkcspad.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
#include "pkcspad.h"
|
||||
#include <assert.h>
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
template<> const byte PKCS_DigestDecoration<SHA>::decoration[] = {0x30,0x21,0x30,0x09,0x06,0x05,0x2B,0x0E,0x03,0x02,0x1A,0x05,0x00,0x04,0x14};
|
||||
template<> const unsigned int PKCS_DigestDecoration<SHA>::length = sizeof(PKCS_DigestDecoration<SHA>::decoration);
|
||||
|
||||
template<> const byte PKCS_DigestDecoration<MD2>::decoration[] = {0x30,0x20,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x02,0x05,0x00,0x04,0x10};
|
||||
template<> const unsigned int PKCS_DigestDecoration<MD2>::length = sizeof(PKCS_DigestDecoration<MD2>::decoration);
|
||||
|
||||
template<> const byte PKCS_DigestDecoration<MD5>::decoration[] = {0x30,0x20,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x04,0x10};
|
||||
template<> const unsigned int PKCS_DigestDecoration<MD5>::length = sizeof(PKCS_DigestDecoration<MD5>::decoration);
|
||||
|
||||
template<> const byte PKCS_DigestDecoration<RIPEMD160>::decoration[] = {0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x24,0x03,0x02,0x01,0x05,0x00,0x04,0x14};
|
||||
template<> const unsigned int PKCS_DigestDecoration<RIPEMD160>::length = sizeof(PKCS_DigestDecoration<RIPEMD160>::decoration);
|
||||
|
||||
template<> const byte PKCS_DigestDecoration<Tiger>::decoration[] = {0x30,0x29,0x30,0x0D,0x06,0x09,0x2B,0x06,0x01,0x04,0x01,0xDA,0x47,0x0C,0x02,0x05,0x00,0x04,0x18};
|
||||
template<> const unsigned int PKCS_DigestDecoration<Tiger>::length = sizeof(PKCS_DigestDecoration<Tiger>::decoration);
|
||||
|
||||
template<> const byte PKCS_DigestDecoration<SHA256>::decoration[] = {0x30,0x31,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0x04,0x20};
|
||||
template<> const unsigned int PKCS_DigestDecoration<SHA256>::length = sizeof(PKCS_DigestDecoration<SHA256>::decoration);
|
||||
|
||||
template<> const byte PKCS_DigestDecoration<SHA384>::decoration[] = {0x30,0x41,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,0x04,0x30};
|
||||
template<> const unsigned int PKCS_DigestDecoration<SHA384>::length = sizeof(PKCS_DigestDecoration<SHA384>::decoration);
|
||||
|
||||
template<> const byte PKCS_DigestDecoration<SHA512>::decoration[] = {0x30,0x51,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0x04,0x40};
|
||||
template<> const unsigned int PKCS_DigestDecoration<SHA512>::length = sizeof(PKCS_DigestDecoration<SHA512>::decoration);
|
||||
|
||||
unsigned int PKCS_EncryptionPaddingScheme::MaxUnpaddedLength(unsigned int paddedLength) const
|
||||
{
|
||||
return SaturatingSubtract(paddedLength/8, 10U);
|
||||
}
|
||||
|
||||
void PKCS_EncryptionPaddingScheme::Pad(RandomNumberGenerator &rng, const byte *input, unsigned int inputLen, byte *pkcsBlock, unsigned int pkcsBlockLen) const
|
||||
{
|
||||
assert (inputLen <= MaxUnpaddedLength(pkcsBlockLen)); // this should be checked by caller
|
||||
|
||||
// convert from bit length to byte length
|
||||
if (pkcsBlockLen % 8 != 0)
|
||||
{
|
||||
pkcsBlock[0] = 0;
|
||||
pkcsBlock++;
|
||||
}
|
||||
pkcsBlockLen /= 8;
|
||||
|
||||
pkcsBlock[0] = 2; // block type 2
|
||||
|
||||
// pad with non-zero random bytes
|
||||
for (unsigned i = 1; i < pkcsBlockLen-inputLen-1; i++)
|
||||
pkcsBlock[i] = (byte)rng.GenerateWord32(1, 0xff);
|
||||
|
||||
pkcsBlock[pkcsBlockLen-inputLen-1] = 0; // separator
|
||||
memcpy(pkcsBlock+pkcsBlockLen-inputLen, input, inputLen);
|
||||
}
|
||||
|
||||
DecodingResult PKCS_EncryptionPaddingScheme::Unpad(const byte *pkcsBlock, unsigned int pkcsBlockLen, byte *output) const
|
||||
{
|
||||
bool invalid = false;
|
||||
unsigned int maxOutputLen = MaxUnpaddedLength(pkcsBlockLen);
|
||||
|
||||
// convert from bit length to byte length
|
||||
if (pkcsBlockLen % 8 != 0)
|
||||
{
|
||||
invalid = (pkcsBlock[0] != 0) || invalid;
|
||||
pkcsBlock++;
|
||||
}
|
||||
pkcsBlockLen /= 8;
|
||||
|
||||
// Require block type 2.
|
||||
invalid = (pkcsBlock[0] != 2) || invalid;
|
||||
|
||||
// skip past the padding until we find the separator
|
||||
unsigned i=1;
|
||||
while (i<pkcsBlockLen && pkcsBlock[i++]) { // null body
|
||||
}
|
||||
assert(i==pkcsBlockLen || pkcsBlock[i-1]==0);
|
||||
|
||||
unsigned int outputLen = pkcsBlockLen - i;
|
||||
invalid = (outputLen > maxOutputLen) || invalid;
|
||||
|
||||
if (invalid)
|
||||
return DecodingResult();
|
||||
|
||||
memcpy (output, pkcsBlock+i, outputLen);
|
||||
return DecodingResult(outputLen);
|
||||
}
|
||||
|
||||
// ********************************************************
|
||||
|
||||
void PKCS1v15_SignatureMessageEncodingMethod::ComputeMessageRepresentative(RandomNumberGenerator &rng,
|
||||
const byte *recoverableMessage, unsigned int recoverableMessageLength,
|
||||
HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
|
||||
byte *representative, unsigned int representativeBitLength) const
|
||||
{
|
||||
unsigned int digestSize = hash.DigestSize();
|
||||
if (digestSize + hashIdentifier.second + 10 > representativeBitLength/8)
|
||||
throw PK_Signer::KeyTooShort();
|
||||
|
||||
unsigned int pkcsBlockLen = representativeBitLength;
|
||||
// convert from bit length to byte length
|
||||
if (pkcsBlockLen % 8 != 0)
|
||||
{
|
||||
representative[0] = 0;
|
||||
representative++;
|
||||
}
|
||||
pkcsBlockLen /= 8;
|
||||
|
||||
representative[0] = 1; // block type 1
|
||||
|
||||
byte *pPadding = representative + 1;
|
||||
byte *pDigest = representative + pkcsBlockLen - digestSize;
|
||||
byte *pHashId = pDigest - hashIdentifier.second;
|
||||
byte *pSeparator = pHashId - 1;
|
||||
|
||||
// pad with 0xff
|
||||
memset(pPadding, 0xff, pSeparator-pPadding);
|
||||
*pSeparator = 0;
|
||||
memcpy(pHashId, hashIdentifier.first, hashIdentifier.second);
|
||||
hash.Final(pDigest);
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -0,0 +1,70 @@
|
||||
#ifndef CRYPTOPP_PKCSPAD_H
|
||||
#define CRYPTOPP_PKCSPAD_H
|
||||
|
||||
#include "cryptlib.h"
|
||||
#include "pubkey.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
//! <a href="http://www.weidai.com/scan-mirror/ca.html#cem_PKCS1-1.5">EME-PKCS1-v1_5</a>
|
||||
class PKCS_EncryptionPaddingScheme : public PK_EncryptionMessageEncodingMethod
|
||||
{
|
||||
public:
|
||||
static const char * StaticAlgorithmName() {return "EME-PKCS1-v1_5";}
|
||||
|
||||
unsigned int MaxUnpaddedLength(unsigned int paddedLength) const;
|
||||
void Pad(RandomNumberGenerator &rng, const byte *raw, unsigned int inputLength, byte *padded, unsigned int paddedLength) const;
|
||||
DecodingResult Unpad(const byte *padded, unsigned int paddedLength, byte *raw) const;
|
||||
};
|
||||
|
||||
template <class H> struct PKCS_DigestDecoration
|
||||
{
|
||||
static const byte decoration[];
|
||||
static const unsigned int length;
|
||||
};
|
||||
|
||||
//! <a href="http://www.weidai.com/scan-mirror/sig.html#sem_PKCS1-1.5">EMSA-PKCS1-v1_5</a>
|
||||
class PKCS1v15_SignatureMessageEncodingMethod : public PK_DeterministicSignatureMessageEncodingMethod
|
||||
{
|
||||
public:
|
||||
static const char * StaticAlgorithmName() {return "EMSA-PKCS1-v1_5";}
|
||||
|
||||
void ComputeMessageRepresentative(RandomNumberGenerator &rng,
|
||||
const byte *recoverableMessage, unsigned int recoverableMessageLength,
|
||||
HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
|
||||
byte *representative, unsigned int representativeBitLength) const;
|
||||
|
||||
struct HashIdentifierLookup
|
||||
{
|
||||
template <class H> struct HashIdentifierLookup2
|
||||
{
|
||||
static HashIdentifier Lookup()
|
||||
{
|
||||
return HashIdentifier(PKCS_DigestDecoration<H>::decoration, PKCS_DigestDecoration<H>::length);
|
||||
}
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
//! PKCS #1 version 1.5, for use with RSAES and RSASS
|
||||
/*! The following hash functions are supported for signature: SHA, MD2, MD5, RIPEMD160, SHA256, SHA384, SHA512. */
|
||||
struct PKCS1v15 : public SignatureStandard, public EncryptionStandard
|
||||
{
|
||||
typedef PKCS_EncryptionPaddingScheme EncryptionMessageEncodingMethod;
|
||||
typedef PKCS1v15_SignatureMessageEncodingMethod SignatureMessageEncodingMethod;
|
||||
};
|
||||
|
||||
// PKCS_DecoratedHashModule can be instantiated with the following
|
||||
// classes as specified in PKCS#1 v2.0 and P1363a
|
||||
class SHA;
|
||||
class MD2;
|
||||
class MD5;
|
||||
class RIPEMD160;
|
||||
class Tiger;
|
||||
class SHA256;
|
||||
class SHA384;
|
||||
class SHA512;
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,579 @@
|
||||
// polynomi.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
// Part of the code for polynomial evaluation and interpolation
|
||||
// originally came from Hal Finney's public domain secsplit.c.
|
||||
|
||||
#include "pch.h"
|
||||
#include "polynomi.h"
|
||||
#include "secblock.h"
|
||||
|
||||
#include <strstream>
|
||||
#include <iostream>
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
template <class T>
|
||||
void PolynomialOver<T>::Randomize(RandomNumberGenerator &rng, const RandomizationParameter ¶meter, const Ring &ring)
|
||||
{
|
||||
m_coefficients.resize(parameter.m_coefficientCount);
|
||||
for (unsigned int i=0; i<m_coefficients.size(); ++i)
|
||||
m_coefficients[i] = ring.RandomElement(rng, parameter.m_coefficientParameter);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void PolynomialOver<T>::FromStr(const char *str, const Ring &ring)
|
||||
{
|
||||
std::istrstream in((char *)str);
|
||||
bool positive = true;
|
||||
CoefficientType coef;
|
||||
unsigned int power;
|
||||
|
||||
while (in)
|
||||
{
|
||||
std::ws(in);
|
||||
if (in.peek() == 'x')
|
||||
coef = ring.MultiplicativeIdentity();
|
||||
else
|
||||
in >> coef;
|
||||
|
||||
std::ws(in);
|
||||
if (in.peek() == 'x')
|
||||
{
|
||||
in.get();
|
||||
std::ws(in);
|
||||
if (in.peek() == '^')
|
||||
{
|
||||
in.get();
|
||||
in >> power;
|
||||
}
|
||||
else
|
||||
power = 1;
|
||||
}
|
||||
else
|
||||
power = 0;
|
||||
|
||||
if (!positive)
|
||||
coef = ring.Inverse(coef);
|
||||
|
||||
SetCoefficient(power, coef, ring);
|
||||
|
||||
std::ws(in);
|
||||
switch (in.get())
|
||||
{
|
||||
case '+':
|
||||
positive = true;
|
||||
break;
|
||||
case '-':
|
||||
positive = false;
|
||||
break;
|
||||
default:
|
||||
return; // something's wrong with the input string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
unsigned int PolynomialOver<T>::CoefficientCount(const Ring &ring) const
|
||||
{
|
||||
unsigned count = m_coefficients.size();
|
||||
while (count && ring.Equal(m_coefficients[count-1], ring.Identity()))
|
||||
count--;
|
||||
const_cast<std::vector<CoefficientType> &>(m_coefficients).resize(count);
|
||||
return count;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
typename PolynomialOver<T>::CoefficientType PolynomialOver<T>::GetCoefficient(unsigned int i, const Ring &ring) const
|
||||
{
|
||||
return (i < m_coefficients.size()) ? m_coefficients[i] : ring.Identity();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PolynomialOver<T>& PolynomialOver<T>::operator=(const PolynomialOver<T>& t)
|
||||
{
|
||||
if (this != &t)
|
||||
{
|
||||
m_coefficients.resize(t.m_coefficients.size());
|
||||
for (unsigned int i=0; i<m_coefficients.size(); i++)
|
||||
m_coefficients[i] = t.m_coefficients[i];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PolynomialOver<T>& PolynomialOver<T>::Accumulate(const PolynomialOver<T>& t, const Ring &ring)
|
||||
{
|
||||
unsigned int count = t.CoefficientCount(ring);
|
||||
|
||||
if (count > CoefficientCount(ring))
|
||||
m_coefficients.resize(count, ring.Identity());
|
||||
|
||||
for (unsigned int i=0; i<count; i++)
|
||||
ring.Accumulate(m_coefficients[i], t.GetCoefficient(i, ring));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PolynomialOver<T>& PolynomialOver<T>::Reduce(const PolynomialOver<T>& t, const Ring &ring)
|
||||
{
|
||||
unsigned int count = t.CoefficientCount(ring);
|
||||
|
||||
if (count > CoefficientCount(ring))
|
||||
m_coefficients.resize(count, ring.Identity());
|
||||
|
||||
for (unsigned int i=0; i<count; i++)
|
||||
ring.Reduce(m_coefficients[i], t.GetCoefficient(i, ring));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
typename PolynomialOver<T>::CoefficientType PolynomialOver<T>::EvaluateAt(const CoefficientType &x, const Ring &ring) const
|
||||
{
|
||||
int degree = Degree(ring);
|
||||
|
||||
if (degree < 0)
|
||||
return ring.Identity();
|
||||
|
||||
CoefficientType result = m_coefficients[degree];
|
||||
for (int j=degree-1; j>=0; j--)
|
||||
{
|
||||
result = ring.Multiply(result, x);
|
||||
ring.Accumulate(result, m_coefficients[j]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PolynomialOver<T>& PolynomialOver<T>::ShiftLeft(unsigned int n, const Ring &ring)
|
||||
{
|
||||
unsigned int i = CoefficientCount(ring) + n;
|
||||
m_coefficients.resize(i, ring.Identity());
|
||||
while (i > n)
|
||||
{
|
||||
i--;
|
||||
m_coefficients[i] = m_coefficients[i-n];
|
||||
}
|
||||
while (i)
|
||||
{
|
||||
i--;
|
||||
m_coefficients[i] = ring.Identity();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PolynomialOver<T>& PolynomialOver<T>::ShiftRight(unsigned int n, const Ring &ring)
|
||||
{
|
||||
unsigned int count = CoefficientCount(ring);
|
||||
if (count > n)
|
||||
{
|
||||
for (unsigned int i=0; i<count-n; i++)
|
||||
m_coefficients[i] = m_coefficients[i+n];
|
||||
m_coefficients.resize(count-n, ring.Identity());
|
||||
}
|
||||
else
|
||||
m_coefficients.resize(0, ring.Identity());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void PolynomialOver<T>::SetCoefficient(unsigned int i, const CoefficientType &value, const Ring &ring)
|
||||
{
|
||||
if (i >= m_coefficients.size())
|
||||
m_coefficients.resize(i+1, ring.Identity());
|
||||
m_coefficients[i] = value;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void PolynomialOver<T>::Negate(const Ring &ring)
|
||||
{
|
||||
unsigned int count = CoefficientCount(ring);
|
||||
for (unsigned int i=0; i<count; i++)
|
||||
m_coefficients[i] = ring.Inverse(m_coefficients[i]);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void PolynomialOver<T>::swap(PolynomialOver<T> &t)
|
||||
{
|
||||
m_coefficients.swap(t.m_coefficients);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool PolynomialOver<T>::Equals(const PolynomialOver<T>& t, const Ring &ring) const
|
||||
{
|
||||
unsigned int count = CoefficientCount(ring);
|
||||
|
||||
if (count != t.CoefficientCount(ring))
|
||||
return false;
|
||||
|
||||
for (unsigned int i=0; i<count; i++)
|
||||
if (!ring.Equal(m_coefficients[i], t.m_coefficients[i]))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PolynomialOver<T> PolynomialOver<T>::Plus(const PolynomialOver<T>& t, const Ring &ring) const
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int count = CoefficientCount(ring);
|
||||
unsigned int tCount = t.CoefficientCount(ring);
|
||||
|
||||
if (count > tCount)
|
||||
{
|
||||
PolynomialOver<T> result(ring, count);
|
||||
|
||||
for (i=0; i<tCount; i++)
|
||||
result.m_coefficients[i] = ring.Add(m_coefficients[i], t.m_coefficients[i]);
|
||||
for (; i<count; i++)
|
||||
result.m_coefficients[i] = m_coefficients[i];
|
||||
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
PolynomialOver<T> result(ring, tCount);
|
||||
|
||||
for (i=0; i<count; i++)
|
||||
result.m_coefficients[i] = ring.Add(m_coefficients[i], t.m_coefficients[i]);
|
||||
for (; i<tCount; i++)
|
||||
result.m_coefficients[i] = t.m_coefficients[i];
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PolynomialOver<T> PolynomialOver<T>::Minus(const PolynomialOver<T>& t, const Ring &ring) const
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int count = CoefficientCount(ring);
|
||||
unsigned int tCount = t.CoefficientCount(ring);
|
||||
|
||||
if (count > tCount)
|
||||
{
|
||||
PolynomialOver<T> result(ring, count);
|
||||
|
||||
for (i=0; i<tCount; i++)
|
||||
result.m_coefficients[i] = ring.Subtract(m_coefficients[i], t.m_coefficients[i]);
|
||||
for (; i<count; i++)
|
||||
result.m_coefficients[i] = m_coefficients[i];
|
||||
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
PolynomialOver<T> result(ring, tCount);
|
||||
|
||||
for (i=0; i<count; i++)
|
||||
result.m_coefficients[i] = ring.Subtract(m_coefficients[i], t.m_coefficients[i]);
|
||||
for (; i<tCount; i++)
|
||||
result.m_coefficients[i] = ring.Inverse(t.m_coefficients[i]);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PolynomialOver<T> PolynomialOver<T>::Inverse(const Ring &ring) const
|
||||
{
|
||||
unsigned int count = CoefficientCount(ring);
|
||||
PolynomialOver<T> result(ring, count);
|
||||
|
||||
for (unsigned int i=0; i<count; i++)
|
||||
result.m_coefficients[i] = ring.Inverse(m_coefficients[i]);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PolynomialOver<T> PolynomialOver<T>::Times(const PolynomialOver<T>& t, const Ring &ring) const
|
||||
{
|
||||
if (IsZero(ring) || t.IsZero(ring))
|
||||
return PolynomialOver<T>();
|
||||
|
||||
unsigned int count1 = CoefficientCount(ring), count2 = t.CoefficientCount(ring);
|
||||
PolynomialOver<T> result(ring, count1 + count2 - 1);
|
||||
|
||||
for (unsigned int i=0; i<count1; i++)
|
||||
for (unsigned int j=0; j<count2; j++)
|
||||
ring.Accumulate(result.m_coefficients[i+j], ring.Multiply(m_coefficients[i], t.m_coefficients[j]));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PolynomialOver<T> PolynomialOver<T>::DividedBy(const PolynomialOver<T>& t, const Ring &ring) const
|
||||
{
|
||||
PolynomialOver<T> remainder, quotient;
|
||||
Divide(remainder, quotient, *this, t, ring);
|
||||
return quotient;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PolynomialOver<T> PolynomialOver<T>::Modulo(const PolynomialOver<T>& t, const Ring &ring) const
|
||||
{
|
||||
PolynomialOver<T> remainder, quotient;
|
||||
Divide(remainder, quotient, *this, t, ring);
|
||||
return remainder;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PolynomialOver<T> PolynomialOver<T>::MultiplicativeInverse(const Ring &ring) const
|
||||
{
|
||||
return Degree(ring)==0 ? ring.MultiplicativeInverse(m_coefficients[0]) : ring.Identity();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool PolynomialOver<T>::IsUnit(const Ring &ring) const
|
||||
{
|
||||
return Degree(ring)==0 && ring.IsUnit(m_coefficients[0]);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
std::istream& PolynomialOver<T>::Input(std::istream &in, const Ring &ring)
|
||||
{
|
||||
char c;
|
||||
unsigned int length = 0;
|
||||
SecBlock<char> str(length + 16);
|
||||
bool paren = false;
|
||||
|
||||
std::ws(in);
|
||||
|
||||
if (in.peek() == '(')
|
||||
{
|
||||
paren = true;
|
||||
in.get();
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
in.read(&c, 1);
|
||||
str[length++] = c;
|
||||
if (length >= str.size())
|
||||
str.Grow(length + 16);
|
||||
}
|
||||
// if we started with a left paren, then read until we find a right paren,
|
||||
// otherwise read until the end of the line
|
||||
while (in && ((paren && c != ')') || (!paren && c != '\n')));
|
||||
|
||||
str[length-1] = '\0';
|
||||
*this = PolynomialOver<T>(str, ring);
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
std::ostream& PolynomialOver<T>::Output(std::ostream &out, const Ring &ring) const
|
||||
{
|
||||
unsigned int i = CoefficientCount(ring);
|
||||
if (i)
|
||||
{
|
||||
bool firstTerm = true;
|
||||
|
||||
while (i--)
|
||||
{
|
||||
if (m_coefficients[i] != ring.Identity())
|
||||
{
|
||||
if (firstTerm)
|
||||
{
|
||||
firstTerm = false;
|
||||
if (!i || !ring.Equal(m_coefficients[i], ring.MultiplicativeIdentity()))
|
||||
out << m_coefficients[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
CoefficientType inverse = ring.Inverse(m_coefficients[i]);
|
||||
std::ostrstream pstr, nstr;
|
||||
|
||||
pstr << m_coefficients[i];
|
||||
nstr << inverse;
|
||||
|
||||
if (pstr.pcount() <= nstr.pcount())
|
||||
{
|
||||
out << " + ";
|
||||
if (!i || !ring.Equal(m_coefficients[i], ring.MultiplicativeIdentity()))
|
||||
out << m_coefficients[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
out << " - ";
|
||||
if (!i || !ring.Equal(inverse, ring.MultiplicativeIdentity()))
|
||||
out << inverse;
|
||||
}
|
||||
}
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
out << "x";
|
||||
break;
|
||||
default:
|
||||
out << "x^" << i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
out << ring.Identity();
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void PolynomialOver<T>::Divide(PolynomialOver<T> &r, PolynomialOver<T> &q, const PolynomialOver<T> &a, const PolynomialOver<T> &d, const Ring &ring)
|
||||
{
|
||||
unsigned int i = a.CoefficientCount(ring);
|
||||
const int dDegree = d.Degree(ring);
|
||||
|
||||
if (dDegree < 0)
|
||||
throw DivideByZero();
|
||||
|
||||
r = a;
|
||||
q.m_coefficients.resize(STDMAX(0, int(i - dDegree)));
|
||||
|
||||
while (i > (unsigned int)dDegree)
|
||||
{
|
||||
--i;
|
||||
q.m_coefficients[i-dDegree] = ring.Divide(r.m_coefficients[i], d.m_coefficients[dDegree]);
|
||||
for (int j=0; j<=dDegree; j++)
|
||||
ring.Reduce(r.m_coefficients[i-dDegree+j], ring.Multiply(q.m_coefficients[i-dDegree], d.m_coefficients[j]));
|
||||
}
|
||||
|
||||
r.CoefficientCount(ring); // resize r.m_coefficients
|
||||
}
|
||||
|
||||
// ********************************************************
|
||||
|
||||
// helper function for Interpolate() and InterpolateAt()
|
||||
template <class T>
|
||||
void RingOfPolynomialsOver<T>::CalculateAlpha(std::vector<CoefficientType> &alpha, const CoefficientType x[], const CoefficientType y[], unsigned int n) const
|
||||
{
|
||||
for (unsigned int j=0; j<n; ++j)
|
||||
alpha[j] = y[j];
|
||||
|
||||
for (unsigned int k=1; k<n; ++k)
|
||||
{
|
||||
for (unsigned int j=n-1; j>=k; --j)
|
||||
{
|
||||
m_ring.Reduce(alpha[j], alpha[j-1]);
|
||||
|
||||
CoefficientType d = m_ring.Subtract(x[j], x[j-k]);
|
||||
if (!m_ring.IsUnit(d))
|
||||
throw InterpolationFailed();
|
||||
alpha[j] = m_ring.Divide(alpha[j], d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
typename RingOfPolynomialsOver<T>::Element RingOfPolynomialsOver<T>::Interpolate(const CoefficientType x[], const CoefficientType y[], unsigned int n) const
|
||||
{
|
||||
assert(n > 0);
|
||||
|
||||
std::vector<CoefficientType> alpha(n);
|
||||
CalculateAlpha(alpha, x, y, n);
|
||||
|
||||
std::vector<CoefficientType> coefficients((size_t)n, m_ring.Identity());
|
||||
coefficients[0] = alpha[n-1];
|
||||
|
||||
for (int j=n-2; j>=0; --j)
|
||||
{
|
||||
for (unsigned int i=n-j-1; i>0; i--)
|
||||
coefficients[i] = m_ring.Subtract(coefficients[i-1], m_ring.Multiply(coefficients[i], x[j]));
|
||||
|
||||
coefficients[0] = m_ring.Subtract(alpha[j], m_ring.Multiply(coefficients[0], x[j]));
|
||||
}
|
||||
|
||||
return PolynomialOver<T>(coefficients.begin(), coefficients.end());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
typename RingOfPolynomialsOver<T>::CoefficientType RingOfPolynomialsOver<T>::InterpolateAt(const CoefficientType &position, const CoefficientType x[], const CoefficientType y[], unsigned int n) const
|
||||
{
|
||||
assert(n > 0);
|
||||
|
||||
std::vector<CoefficientType> alpha(n);
|
||||
CalculateAlpha(alpha, x, y, n);
|
||||
|
||||
CoefficientType result = alpha[n-1];
|
||||
for (int j=n-2; j>=0; --j)
|
||||
{
|
||||
result = m_ring.Multiply(result, m_ring.Subtract(position, x[j]));
|
||||
m_ring.Accumulate(result, alpha[j]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class Ring, class Element>
|
||||
void PrepareBulkPolynomialInterpolation(const Ring &ring, Element *w, const Element x[], unsigned int n)
|
||||
{
|
||||
for (unsigned int i=0; i<n; i++)
|
||||
{
|
||||
Element t = ring.MultiplicativeIdentity();
|
||||
for (unsigned int j=0; j<n; j++)
|
||||
if (i != j)
|
||||
t = ring.Multiply(t, ring.Subtract(x[i], x[j]));
|
||||
w[i] = ring.MultiplicativeInverse(t);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Ring, class Element>
|
||||
void PrepareBulkPolynomialInterpolationAt(const Ring &ring, Element *v, const Element &position, const Element x[], const Element w[], unsigned int n)
|
||||
{
|
||||
assert(n > 0);
|
||||
|
||||
std::vector<Element> a(2*n-1);
|
||||
unsigned int i;
|
||||
|
||||
for (i=0; i<n; i++)
|
||||
a[n-1+i] = ring.Subtract(position, x[i]);
|
||||
|
||||
for (i=n-1; i>1; i--)
|
||||
a[i-1] = ring.Multiply(a[2*i], a[2*i-1]);
|
||||
|
||||
a[0] = ring.MultiplicativeIdentity();
|
||||
|
||||
for (i=0; i<n-1; i++)
|
||||
{
|
||||
std::swap(a[2*i+1], a[2*i+2]);
|
||||
a[2*i+1] = ring.Multiply(a[i], a[2*i+1]);
|
||||
a[2*i+2] = ring.Multiply(a[i], a[2*i+2]);
|
||||
}
|
||||
|
||||
for (i=0; i<n; i++)
|
||||
v[i] = ring.Multiply(a[n-1+i], w[i]);
|
||||
}
|
||||
|
||||
template <class Ring, class Element>
|
||||
Element BulkPolynomialInterpolateAt(const Ring &ring, const Element y[], const Element v[], unsigned int n)
|
||||
{
|
||||
Element result = ring.Identity();
|
||||
for (unsigned int i=0; i<n; i++)
|
||||
ring.Accumulate(result, ring.Multiply(y[i], v[i]));
|
||||
return result;
|
||||
}
|
||||
|
||||
// ********************************************************
|
||||
|
||||
template <class T, int instance>
|
||||
const PolynomialOverFixedRing<T, instance> &PolynomialOverFixedRing<T, instance>::Zero()
|
||||
{
|
||||
static const PolynomialOverFixedRing<T, instance> zero;
|
||||
return zero;
|
||||
}
|
||||
|
||||
template <class T, int instance>
|
||||
const PolynomialOverFixedRing<T, instance> &PolynomialOverFixedRing<T, instance>::One()
|
||||
{
|
||||
static const PolynomialOverFixedRing<T, instance> one = fixedRing.MultiplicativeIdentity();
|
||||
return one;
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -0,0 +1,451 @@
|
||||
#ifndef CRYPTOPP_POLYNOMI_H
|
||||
#define CRYPTOPP_POLYNOMI_H
|
||||
|
||||
/*! \file */
|
||||
|
||||
#include "cryptlib.h"
|
||||
#include "misc.h"
|
||||
#include "algebra.h"
|
||||
|
||||
#include <iosfwd>
|
||||
#include <vector>
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
//! represents single-variable polynomials over arbitrary rings
|
||||
/*! \nosubgrouping */
|
||||
template <class T> class PolynomialOver
|
||||
{
|
||||
public:
|
||||
//! \name ENUMS, EXCEPTIONS, and TYPEDEFS
|
||||
//@{
|
||||
//! division by zero exception
|
||||
class DivideByZero : public Exception
|
||||
{
|
||||
public:
|
||||
DivideByZero() : Exception(OTHER_ERROR, "PolynomialOver<T>: division by zero") {}
|
||||
};
|
||||
|
||||
//! specify the distribution for randomization functions
|
||||
class RandomizationParameter
|
||||
{
|
||||
public:
|
||||
RandomizationParameter(unsigned int coefficientCount, const typename T::RandomizationParameter &coefficientParameter )
|
||||
: m_coefficientCount(coefficientCount), m_coefficientParameter(coefficientParameter) {}
|
||||
|
||||
private:
|
||||
unsigned int m_coefficientCount;
|
||||
typename T::RandomizationParameter m_coefficientParameter;
|
||||
friend class PolynomialOver<T>;
|
||||
};
|
||||
|
||||
typedef T Ring;
|
||||
typedef typename T::Element CoefficientType;
|
||||
//@}
|
||||
|
||||
//! \name CREATORS
|
||||
//@{
|
||||
//! creates the zero polynomial
|
||||
PolynomialOver() {}
|
||||
|
||||
//!
|
||||
PolynomialOver(const Ring &ring, unsigned int count)
|
||||
: m_coefficients((size_t)count, ring.Identity()) {}
|
||||
|
||||
//! copy constructor
|
||||
PolynomialOver(const PolynomialOver<Ring> &t)
|
||||
: m_coefficients(t.m_coefficients.size()) {*this = t;}
|
||||
|
||||
//! construct constant polynomial
|
||||
PolynomialOver(const CoefficientType &element)
|
||||
: m_coefficients(1, element) {}
|
||||
|
||||
//! construct polynomial with specified coefficients, starting from coefficient of x^0
|
||||
template <typename Iterator> PolynomialOver(Iterator begin, Iterator end)
|
||||
: m_coefficients(begin, end) {}
|
||||
|
||||
//! convert from string
|
||||
PolynomialOver(const char *str, const Ring &ring) {FromStr(str, ring);}
|
||||
|
||||
//! convert from big-endian byte array
|
||||
PolynomialOver(const byte *encodedPolynomialOver, unsigned int byteCount);
|
||||
|
||||
//! convert from Basic Encoding Rules encoded byte array
|
||||
explicit PolynomialOver(const byte *BEREncodedPolynomialOver);
|
||||
|
||||
//! convert from BER encoded byte array stored in a BufferedTransformation object
|
||||
explicit PolynomialOver(BufferedTransformation &bt);
|
||||
|
||||
//! create a random PolynomialOver<T>
|
||||
PolynomialOver(RandomNumberGenerator &rng, const RandomizationParameter ¶meter, const Ring &ring)
|
||||
{Randomize(rng, parameter, ring);}
|
||||
//@}
|
||||
|
||||
//! \name ACCESSORS
|
||||
//@{
|
||||
//! the zero polynomial will return a degree of -1
|
||||
int Degree(const Ring &ring) const {return int(CoefficientCount(ring))-1;}
|
||||
//!
|
||||
unsigned int CoefficientCount(const Ring &ring) const;
|
||||
//! return coefficient for x^i
|
||||
CoefficientType GetCoefficient(unsigned int i, const Ring &ring) const;
|
||||
//@}
|
||||
|
||||
//! \name MANIPULATORS
|
||||
//@{
|
||||
//!
|
||||
PolynomialOver<Ring>& operator=(const PolynomialOver<Ring>& t);
|
||||
|
||||
//!
|
||||
void Randomize(RandomNumberGenerator &rng, const RandomizationParameter ¶meter, const Ring &ring);
|
||||
|
||||
//! set the coefficient for x^i to value
|
||||
void SetCoefficient(unsigned int i, const CoefficientType &value, const Ring &ring);
|
||||
|
||||
//!
|
||||
void Negate(const Ring &ring);
|
||||
|
||||
//!
|
||||
void swap(PolynomialOver<Ring> &t);
|
||||
//@}
|
||||
|
||||
|
||||
//! \name BASIC ARITHMETIC ON POLYNOMIALS
|
||||
//@{
|
||||
bool Equals(const PolynomialOver<Ring> &t, const Ring &ring) const;
|
||||
bool IsZero(const Ring &ring) const {return CoefficientCount(ring)==0;}
|
||||
|
||||
PolynomialOver<Ring> Plus(const PolynomialOver<Ring>& t, const Ring &ring) const;
|
||||
PolynomialOver<Ring> Minus(const PolynomialOver<Ring>& t, const Ring &ring) const;
|
||||
PolynomialOver<Ring> Inverse(const Ring &ring) const;
|
||||
|
||||
PolynomialOver<Ring> Times(const PolynomialOver<Ring>& t, const Ring &ring) const;
|
||||
PolynomialOver<Ring> DividedBy(const PolynomialOver<Ring>& t, const Ring &ring) const;
|
||||
PolynomialOver<Ring> Modulo(const PolynomialOver<Ring>& t, const Ring &ring) const;
|
||||
PolynomialOver<Ring> MultiplicativeInverse(const Ring &ring) const;
|
||||
bool IsUnit(const Ring &ring) const;
|
||||
|
||||
PolynomialOver<Ring>& Accumulate(const PolynomialOver<Ring>& t, const Ring &ring);
|
||||
PolynomialOver<Ring>& Reduce(const PolynomialOver<Ring>& t, const Ring &ring);
|
||||
|
||||
//!
|
||||
PolynomialOver<Ring> Doubled(const Ring &ring) const {return Plus(*this, ring);}
|
||||
//!
|
||||
PolynomialOver<Ring> Squared(const Ring &ring) const {return Times(*this, ring);}
|
||||
|
||||
CoefficientType EvaluateAt(const CoefficientType &x, const Ring &ring) const;
|
||||
|
||||
PolynomialOver<Ring>& ShiftLeft(unsigned int n, const Ring &ring);
|
||||
PolynomialOver<Ring>& ShiftRight(unsigned int n, const Ring &ring);
|
||||
|
||||
//! calculate r and q such that (a == d*q + r) && (0 <= degree of r < degree of d)
|
||||
static void Divide(PolynomialOver<Ring> &r, PolynomialOver<Ring> &q, const PolynomialOver<Ring> &a, const PolynomialOver<Ring> &d, const Ring &ring);
|
||||
//@}
|
||||
|
||||
//! \name INPUT/OUTPUT
|
||||
//@{
|
||||
std::istream& Input(std::istream &in, const Ring &ring);
|
||||
std::ostream& Output(std::ostream &out, const Ring &ring) const;
|
||||
//@}
|
||||
|
||||
private:
|
||||
void FromStr(const char *str, const Ring &ring);
|
||||
|
||||
std::vector<CoefficientType> m_coefficients;
|
||||
};
|
||||
|
||||
//! Polynomials over a fixed ring
|
||||
/*! Having a fixed ring allows overloaded operators */
|
||||
template <class T, int instance> class PolynomialOverFixedRing : private PolynomialOver<T>
|
||||
{
|
||||
typedef PolynomialOver<T> B;
|
||||
typedef PolynomialOverFixedRing<T, instance> ThisType;
|
||||
|
||||
public:
|
||||
typedef T Ring;
|
||||
typedef typename T::Element CoefficientType;
|
||||
typedef typename B::DivideByZero DivideByZero;
|
||||
typedef typename B::RandomizationParameter RandomizationParameter;
|
||||
|
||||
//! \name CREATORS
|
||||
//@{
|
||||
//! creates the zero polynomial
|
||||
PolynomialOverFixedRing(unsigned int count = 0) : B(fixedRing, count) {}
|
||||
|
||||
//! copy constructor
|
||||
PolynomialOverFixedRing(const ThisType &t) : B(t) {}
|
||||
|
||||
explicit PolynomialOverFixedRing(const B &t) : B(t) {}
|
||||
|
||||
//! construct constant polynomial
|
||||
PolynomialOverFixedRing(const CoefficientType &element) : B(element) {}
|
||||
|
||||
//! construct polynomial with specified coefficients, starting from coefficient of x^0
|
||||
template <typename Iterator> PolynomialOverFixedRing(Iterator first, Iterator last)
|
||||
: B(first, last) {}
|
||||
|
||||
//! convert from string
|
||||
explicit PolynomialOverFixedRing(const char *str) : B(str, fixedRing) {}
|
||||
|
||||
//! convert from big-endian byte array
|
||||
PolynomialOverFixedRing(const byte *encodedPoly, unsigned int byteCount) : B(encodedPoly, byteCount) {}
|
||||
|
||||
//! convert from Basic Encoding Rules encoded byte array
|
||||
explicit PolynomialOverFixedRing(const byte *BEREncodedPoly) : B(BEREncodedPoly) {}
|
||||
|
||||
//! convert from BER encoded byte array stored in a BufferedTransformation object
|
||||
explicit PolynomialOverFixedRing(BufferedTransformation &bt) : B(bt) {}
|
||||
|
||||
//! create a random PolynomialOverFixedRing
|
||||
PolynomialOverFixedRing(RandomNumberGenerator &rng, const RandomizationParameter ¶meter) : B(rng, parameter, fixedRing) {}
|
||||
|
||||
static const ThisType &Zero();
|
||||
static const ThisType &One();
|
||||
//@}
|
||||
|
||||
//! \name ACCESSORS
|
||||
//@{
|
||||
//! the zero polynomial will return a degree of -1
|
||||
int Degree() const {return B::Degree(fixedRing);}
|
||||
//! degree + 1
|
||||
unsigned int CoefficientCount() const {return B::CoefficientCount(fixedRing);}
|
||||
//! return coefficient for x^i
|
||||
CoefficientType GetCoefficient(unsigned int i) const {return B::GetCoefficient(i, fixedRing);}
|
||||
//! return coefficient for x^i
|
||||
CoefficientType operator[](unsigned int i) const {return B::GetCoefficient(i, fixedRing);}
|
||||
//@}
|
||||
|
||||
//! \name MANIPULATORS
|
||||
//@{
|
||||
//!
|
||||
ThisType& operator=(const ThisType& t) {B::operator=(t); return *this;}
|
||||
//!
|
||||
ThisType& operator+=(const ThisType& t) {Accumulate(t, fixedRing); return *this;}
|
||||
//!
|
||||
ThisType& operator-=(const ThisType& t) {Reduce(t, fixedRing); return *this;}
|
||||
//!
|
||||
ThisType& operator*=(const ThisType& t) {return *this = *this*t;}
|
||||
//!
|
||||
ThisType& operator/=(const ThisType& t) {return *this = *this/t;}
|
||||
//!
|
||||
ThisType& operator%=(const ThisType& t) {return *this = *this%t;}
|
||||
|
||||
//!
|
||||
ThisType& operator<<=(unsigned int n) {ShiftLeft(n, fixedRing); return *this;}
|
||||
//!
|
||||
ThisType& operator>>=(unsigned int n) {ShiftRight(n, fixedRing); return *this;}
|
||||
|
||||
//! set the coefficient for x^i to value
|
||||
void SetCoefficient(unsigned int i, const CoefficientType &value) {B::SetCoefficient(i, value, fixedRing);}
|
||||
|
||||
//!
|
||||
void Randomize(RandomNumberGenerator &rng, const RandomizationParameter ¶meter) {B::Randomize(rng, parameter, fixedRing);}
|
||||
|
||||
//!
|
||||
void Negate() {B::Negate(fixedRing);}
|
||||
|
||||
void swap(ThisType &t) {B::swap(t);}
|
||||
//@}
|
||||
|
||||
//! \name UNARY OPERATORS
|
||||
//@{
|
||||
//!
|
||||
bool operator!() const {return CoefficientCount()==0;}
|
||||
//!
|
||||
ThisType operator+() const {return *this;}
|
||||
//!
|
||||
ThisType operator-() const {return ThisType(Inverse(fixedRing));}
|
||||
//@}
|
||||
|
||||
//! \name BINARY OPERATORS
|
||||
//@{
|
||||
//!
|
||||
friend ThisType operator>>(ThisType a, unsigned int n) {return ThisType(a>>=n);}
|
||||
//!
|
||||
friend ThisType operator<<(ThisType a, unsigned int n) {return ThisType(a<<=n);}
|
||||
//@}
|
||||
|
||||
//! \name OTHER ARITHMETIC FUNCTIONS
|
||||
//@{
|
||||
//!
|
||||
ThisType MultiplicativeInverse() const {return ThisType(B::MultiplicativeInverse(fixedRing));}
|
||||
//!
|
||||
bool IsUnit() const {return B::IsUnit(fixedRing);}
|
||||
|
||||
//!
|
||||
ThisType Doubled() const {return ThisType(B::Doubled(fixedRing));}
|
||||
//!
|
||||
ThisType Squared() const {return ThisType(B::Squared(fixedRing));}
|
||||
|
||||
CoefficientType EvaluateAt(const CoefficientType &x) const {return B::EvaluateAt(x, fixedRing);}
|
||||
|
||||
//! calculate r and q such that (a == d*q + r) && (0 <= r < abs(d))
|
||||
static void Divide(ThisType &r, ThisType &q, const ThisType &a, const ThisType &d)
|
||||
{B::Divide(r, q, a, d, fixedRing);}
|
||||
//@}
|
||||
|
||||
//! \name INPUT/OUTPUT
|
||||
//@{
|
||||
//!
|
||||
friend std::istream& operator>>(std::istream& in, ThisType &a)
|
||||
{return a.Input(in, fixedRing);}
|
||||
//!
|
||||
friend std::ostream& operator<<(std::ostream& out, const ThisType &a)
|
||||
{return a.Output(out, fixedRing);}
|
||||
//@}
|
||||
|
||||
private:
|
||||
static const Ring fixedRing;
|
||||
};
|
||||
|
||||
//! Ring of polynomials over another ring
|
||||
template <class T> class RingOfPolynomialsOver : public AbstractEuclideanDomain<PolynomialOver<T> >
|
||||
{
|
||||
public:
|
||||
typedef T CoefficientRing;
|
||||
typedef PolynomialOver<T> Element;
|
||||
typedef typename Element::CoefficientType CoefficientType;
|
||||
typedef typename Element::RandomizationParameter RandomizationParameter;
|
||||
|
||||
RingOfPolynomialsOver(const CoefficientRing &ring) : m_ring(ring) {}
|
||||
|
||||
Element RandomElement(RandomNumberGenerator &rng, const RandomizationParameter ¶meter)
|
||||
{return Element(rng, parameter, m_ring);}
|
||||
|
||||
bool Equal(const Element &a, const Element &b) const
|
||||
{return a.Equals(b, m_ring);}
|
||||
|
||||
const Element& Identity() const
|
||||
{return result = m_ring.Identity();}
|
||||
|
||||
const Element& Add(const Element &a, const Element &b) const
|
||||
{return result = a.Plus(b, m_ring);}
|
||||
|
||||
Element& Accumulate(Element &a, const Element &b) const
|
||||
{a.Accumulate(b, m_ring); return a;}
|
||||
|
||||
const Element& Inverse(const Element &a) const
|
||||
{return result = a.Inverse(m_ring);}
|
||||
|
||||
const Element& Subtract(const Element &a, const Element &b) const
|
||||
{return result = a.Minus(b, m_ring);}
|
||||
|
||||
Element& Reduce(Element &a, const Element &b) const
|
||||
{return a.Reduce(b, m_ring);}
|
||||
|
||||
const Element& Double(const Element &a) const
|
||||
{return result = a.Doubled(m_ring);}
|
||||
|
||||
const Element& MultiplicativeIdentity() const
|
||||
{return result = m_ring.MultiplicativeIdentity();}
|
||||
|
||||
const Element& Multiply(const Element &a, const Element &b) const
|
||||
{return result = a.Times(b, m_ring);}
|
||||
|
||||
const Element& Square(const Element &a) const
|
||||
{return result = a.Squared(m_ring);}
|
||||
|
||||
bool IsUnit(const Element &a) const
|
||||
{return a.IsUnit(m_ring);}
|
||||
|
||||
const Element& MultiplicativeInverse(const Element &a) const
|
||||
{return result = a.MultiplicativeInverse(m_ring);}
|
||||
|
||||
const Element& Divide(const Element &a, const Element &b) const
|
||||
{return result = a.DividedBy(b, m_ring);}
|
||||
|
||||
const Element& Mod(const Element &a, const Element &b) const
|
||||
{return result = a.Modulo(b, m_ring);}
|
||||
|
||||
void DivisionAlgorithm(Element &r, Element &q, const Element &a, const Element &d) const
|
||||
{Element::Divide(r, q, a, d, m_ring);}
|
||||
|
||||
class InterpolationFailed : public Exception
|
||||
{
|
||||
public:
|
||||
InterpolationFailed() : Exception(OTHER_ERROR, "RingOfPolynomialsOver<T>: interpolation failed") {}
|
||||
};
|
||||
|
||||
Element Interpolate(const CoefficientType x[], const CoefficientType y[], unsigned int n) const;
|
||||
|
||||
// a faster version of Interpolate(x, y, n).EvaluateAt(position)
|
||||
CoefficientType InterpolateAt(const CoefficientType &position, const CoefficientType x[], const CoefficientType y[], unsigned int n) const;
|
||||
/*
|
||||
void PrepareBulkInterpolation(CoefficientType *w, const CoefficientType x[], unsigned int n) const;
|
||||
void PrepareBulkInterpolationAt(CoefficientType *v, const CoefficientType &position, const CoefficientType x[], const CoefficientType w[], unsigned int n) const;
|
||||
CoefficientType BulkInterpolateAt(const CoefficientType y[], const CoefficientType v[], unsigned int n) const;
|
||||
*/
|
||||
protected:
|
||||
void CalculateAlpha(std::vector<CoefficientType> &alpha, const CoefficientType x[], const CoefficientType y[], unsigned int n) const;
|
||||
|
||||
CoefficientRing m_ring;
|
||||
};
|
||||
|
||||
template <class Ring, class Element>
|
||||
void PrepareBulkPolynomialInterpolation(const Ring &ring, Element *w, const Element x[], unsigned int n);
|
||||
template <class Ring, class Element>
|
||||
void PrepareBulkPolynomialInterpolationAt(const Ring &ring, Element *v, const Element &position, const Element x[], const Element w[], unsigned int n);
|
||||
template <class Ring, class Element>
|
||||
Element BulkPolynomialInterpolateAt(const Ring &ring, const Element y[], const Element v[], unsigned int n);
|
||||
|
||||
//!
|
||||
template <class T, int instance>
|
||||
inline bool operator==(const CryptoPP::PolynomialOverFixedRing<T, instance> &a, const CryptoPP::PolynomialOverFixedRing<T, instance> &b)
|
||||
{return a.Equals(b, fixedRing);}
|
||||
//!
|
||||
template <class T, int instance>
|
||||
inline bool operator!=(const CryptoPP::PolynomialOverFixedRing<T, instance> &a, const CryptoPP::PolynomialOverFixedRing<T, instance> &b)
|
||||
{return !(a==b);}
|
||||
|
||||
//!
|
||||
template <class T, int instance>
|
||||
inline bool operator> (const CryptoPP::PolynomialOverFixedRing<T, instance> &a, const CryptoPP::PolynomialOverFixedRing<T, instance> &b)
|
||||
{return a.Degree() > b.Degree();}
|
||||
//!
|
||||
template <class T, int instance>
|
||||
inline bool operator>=(const CryptoPP::PolynomialOverFixedRing<T, instance> &a, const CryptoPP::PolynomialOverFixedRing<T, instance> &b)
|
||||
{return a.Degree() >= b.Degree();}
|
||||
//!
|
||||
template <class T, int instance>
|
||||
inline bool operator< (const CryptoPP::PolynomialOverFixedRing<T, instance> &a, const CryptoPP::PolynomialOverFixedRing<T, instance> &b)
|
||||
{return a.Degree() < b.Degree();}
|
||||
//!
|
||||
template <class T, int instance>
|
||||
inline bool operator<=(const CryptoPP::PolynomialOverFixedRing<T, instance> &a, const CryptoPP::PolynomialOverFixedRing<T, instance> &b)
|
||||
{return a.Degree() <= b.Degree();}
|
||||
|
||||
//!
|
||||
template <class T, int instance>
|
||||
inline CryptoPP::PolynomialOverFixedRing<T, instance> operator+(const CryptoPP::PolynomialOverFixedRing<T, instance> &a, const CryptoPP::PolynomialOverFixedRing<T, instance> &b)
|
||||
{return CryptoPP::PolynomialOverFixedRing<T, instance>(a.Plus(b, fixedRing));}
|
||||
//!
|
||||
template <class T, int instance>
|
||||
inline CryptoPP::PolynomialOverFixedRing<T, instance> operator-(const CryptoPP::PolynomialOverFixedRing<T, instance> &a, const CryptoPP::PolynomialOverFixedRing<T, instance> &b)
|
||||
{return CryptoPP::PolynomialOverFixedRing<T, instance>(a.Minus(b, fixedRing));}
|
||||
//!
|
||||
template <class T, int instance>
|
||||
inline CryptoPP::PolynomialOverFixedRing<T, instance> operator*(const CryptoPP::PolynomialOverFixedRing<T, instance> &a, const CryptoPP::PolynomialOverFixedRing<T, instance> &b)
|
||||
{return CryptoPP::PolynomialOverFixedRing<T, instance>(a.Times(b, fixedRing));}
|
||||
//!
|
||||
template <class T, int instance>
|
||||
inline CryptoPP::PolynomialOverFixedRing<T, instance> operator/(const CryptoPP::PolynomialOverFixedRing<T, instance> &a, const CryptoPP::PolynomialOverFixedRing<T, instance> &b)
|
||||
{return CryptoPP::PolynomialOverFixedRing<T, instance>(a.DividedBy(b, fixedRing));}
|
||||
//!
|
||||
template <class T, int instance>
|
||||
inline CryptoPP::PolynomialOverFixedRing<T, instance> operator%(const CryptoPP::PolynomialOverFixedRing<T, instance> &a, const CryptoPP::PolynomialOverFixedRing<T, instance> &b)
|
||||
{return CryptoPP::PolynomialOverFixedRing<T, instance>(a.Modulo(b, fixedRing));}
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
NAMESPACE_BEGIN(std)
|
||||
template<class T> inline void swap(CryptoPP::PolynomialOver<T> &a, CryptoPP::PolynomialOver<T> &b)
|
||||
{
|
||||
a.swap(b);
|
||||
}
|
||||
template<class T, int i> inline void swap(CryptoPP::PolynomialOverFixedRing<T,i> &a, CryptoPP::PolynomialOverFixedRing<T,i> &b)
|
||||
{
|
||||
a.swap(b);
|
||||
}
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,126 @@
|
||||
// pssr.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
#include "pssr.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
template<> const byte EMSA2HashId<SHA>::id = 0x33;
|
||||
template<> const byte EMSA2HashId<RIPEMD160>::id = 0x31;
|
||||
|
||||
unsigned int PSSR_MEM_Base::MaxRecoverableLength(unsigned int representativeBitLength, unsigned int hashIdentifierLength, unsigned int digestLength) const
|
||||
{
|
||||
if (AllowRecovery())
|
||||
{
|
||||
unsigned int saltLen = SaltLen(digestLength);
|
||||
unsigned int minPadLen = MinPadLen(digestLength);
|
||||
return SaturatingSubtract(representativeBitLength, 8*(minPadLen + saltLen + digestLength + hashIdentifierLength) + 9) / 8;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool PSSR_MEM_Base::IsProbabilistic() const
|
||||
{
|
||||
return SaltLen(1) > 0;
|
||||
}
|
||||
|
||||
bool PSSR_MEM_Base::AllowNonrecoverablePart() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PSSR_MEM_Base::RecoverablePartFirst() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void PSSR_MEM_Base::ComputeMessageRepresentative(RandomNumberGenerator &rng,
|
||||
const byte *recoverableMessage, unsigned int recoverableMessageLength,
|
||||
HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
|
||||
byte *representative, unsigned int representativeBitLength) const
|
||||
{
|
||||
const unsigned int u = hashIdentifier.second + 1;
|
||||
const unsigned int representativeByteLength = BitsToBytes(representativeBitLength);
|
||||
const unsigned int digestSize = hash.DigestSize();
|
||||
const unsigned int saltSize = SaltLen(digestSize);
|
||||
byte *const h = representative + representativeByteLength - u - digestSize;
|
||||
|
||||
SecByteBlock digest(digestSize), salt(saltSize);
|
||||
hash.Final(digest);
|
||||
rng.GenerateBlock(salt, saltSize);
|
||||
|
||||
// compute H = hash of M'
|
||||
byte c[8];
|
||||
UnalignedPutWord(BIG_ENDIAN_ORDER, c, (word32)SafeRightShift<29>(recoverableMessageLength));
|
||||
UnalignedPutWord(BIG_ENDIAN_ORDER, c+4, word32(recoverableMessageLength << 3));
|
||||
hash.Update(c, 8);
|
||||
hash.Update(recoverableMessage, recoverableMessageLength);
|
||||
hash.Update(digest, digestSize);
|
||||
hash.Update(salt, saltSize);
|
||||
hash.Final(h);
|
||||
|
||||
// compute representative
|
||||
GetMGF().GenerateAndMask(hash, representative, representativeByteLength - u - digestSize, h, digestSize, false);
|
||||
byte *xorStart = representative + representativeByteLength - u - digestSize - salt.size() - recoverableMessageLength - 1;
|
||||
xorStart[0] ^= 1;
|
||||
xorbuf(xorStart + 1, recoverableMessage, recoverableMessageLength);
|
||||
xorbuf(xorStart + 1 + recoverableMessageLength, salt, salt.size());
|
||||
memcpy(representative + representativeByteLength - u, hashIdentifier.first, hashIdentifier.second);
|
||||
representative[representativeByteLength - 1] = hashIdentifier.second ? 0xcc : 0xbc;
|
||||
if (representativeBitLength % 8 != 0)
|
||||
representative[0] = (byte)Crop(representative[0], representativeBitLength % 8);
|
||||
}
|
||||
|
||||
DecodingResult PSSR_MEM_Base::RecoverMessageFromRepresentative(
|
||||
HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
|
||||
byte *representative, unsigned int representativeBitLength,
|
||||
byte *recoverableMessage) const
|
||||
{
|
||||
const unsigned int u = hashIdentifier.second + 1;
|
||||
const unsigned int representativeByteLength = BitsToBytes(representativeBitLength);
|
||||
const unsigned int digestSize = hash.DigestSize();
|
||||
const unsigned int saltSize = SaltLen(digestSize);
|
||||
const byte *const h = representative + representativeByteLength - u - digestSize;
|
||||
|
||||
SecByteBlock digest(digestSize);
|
||||
hash.Final(digest);
|
||||
|
||||
DecodingResult result(0);
|
||||
bool &valid = result.isValidCoding;
|
||||
unsigned int &recoverableMessageLength = result.messageLength;
|
||||
|
||||
valid = (representative[representativeByteLength - 1] == (hashIdentifier.second ? 0xcc : 0xbc)) && valid;
|
||||
valid = (memcmp(representative + representativeByteLength - u, hashIdentifier.first, hashIdentifier.second) == 0) && valid;
|
||||
|
||||
GetMGF().GenerateAndMask(hash, representative, representativeByteLength - u - digestSize, h, digestSize);
|
||||
if (representativeBitLength % 8 != 0)
|
||||
representative[0] = (byte)Crop(representative[0], representativeBitLength % 8);
|
||||
|
||||
// extract salt and recoverableMessage from DB = 00 ... || 01 || M || salt
|
||||
byte *salt = representative + representativeByteLength - u - digestSize - saltSize;
|
||||
byte *M = std::find_if(representative, salt-1, std::bind2nd(std::not_equal_to<byte>(), 0));
|
||||
if (*M == 0x01 && (unsigned int)(M - representative - (representativeBitLength % 8 != 0)) >= MinPadLen(digestSize))
|
||||
{
|
||||
recoverableMessageLength = salt-M-1;
|
||||
memcpy(recoverableMessage, M+1, recoverableMessageLength);
|
||||
}
|
||||
else
|
||||
valid = false;
|
||||
|
||||
// verify H = hash of M'
|
||||
byte c[8];
|
||||
UnalignedPutWord(BIG_ENDIAN_ORDER, c, (word32)SafeRightShift<29>(recoverableMessageLength));
|
||||
UnalignedPutWord(BIG_ENDIAN_ORDER, c+4, word32(recoverableMessageLength << 3));
|
||||
hash.Update(c, 8);
|
||||
hash.Update(recoverableMessage, recoverableMessageLength);
|
||||
hash.Update(digest, digestSize);
|
||||
hash.Update(salt, saltSize);
|
||||
valid = hash.Verify(h) && valid;
|
||||
|
||||
if (!AllowRecovery() && valid && recoverableMessageLength != 0)
|
||||
{throw NotImplemented("PSSR_MEM: message recovery disabled");}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -0,0 +1,86 @@
|
||||
#ifndef CRYPTOPP_PSSR_H
|
||||
#define CRYPTOPP_PSSR_H
|
||||
|
||||
#include "pubkey.h"
|
||||
#include <functional>
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
class PSSR_MEM_Base : public PK_RecoverableSignatureMessageEncodingMethod
|
||||
{
|
||||
virtual bool AllowRecovery() const =0;
|
||||
virtual unsigned int SaltLen(unsigned int hashLen) const =0;
|
||||
virtual unsigned int MinPadLen(unsigned int hashLen) const =0;
|
||||
virtual const MaskGeneratingFunction & GetMGF() const =0;
|
||||
|
||||
public:
|
||||
unsigned int MaxRecoverableLength(unsigned int representativeBitLength, unsigned int hashIdentifierLength, unsigned int digestLength) const;
|
||||
bool IsProbabilistic() const;
|
||||
bool AllowNonrecoverablePart() const;
|
||||
bool RecoverablePartFirst() const;
|
||||
void ComputeMessageRepresentative(RandomNumberGenerator &rng,
|
||||
const byte *recoverableMessage, unsigned int recoverableMessageLength,
|
||||
HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
|
||||
byte *representative, unsigned int representativeBitLength) const;
|
||||
DecodingResult RecoverMessageFromRepresentative(
|
||||
HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
|
||||
byte *representative, unsigned int representativeBitLength,
|
||||
byte *recoverableMessage) const;
|
||||
};
|
||||
|
||||
template <class H> struct EMSA2HashId
|
||||
{
|
||||
static const byte id;
|
||||
};
|
||||
|
||||
// EMSA2HashId can be instantiated with the following two classes.
|
||||
class SHA;
|
||||
class RIPEMD160;
|
||||
|
||||
template <class BASE>
|
||||
class EMSA2HashIdLookup : public BASE
|
||||
{
|
||||
public:
|
||||
struct HashIdentifierLookup
|
||||
{
|
||||
template <class H> struct HashIdentifierLookup2
|
||||
{
|
||||
static HashIdentifier Lookup()
|
||||
{
|
||||
return HashIdentifier(&EMSA2HashId<H>::id, 1);
|
||||
}
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
template <bool USE_HASH_ID> class PSSR_MEM_BaseWithHashId;
|
||||
template<> class PSSR_MEM_BaseWithHashId<true> : public EMSA2HashIdLookup<PSSR_MEM_Base> {};
|
||||
template<> class PSSR_MEM_BaseWithHashId<false> : public PSSR_MEM_Base {};
|
||||
|
||||
template <bool ALLOW_RECOVERY, class MGF=P1363_MGF1, int SALT_LEN=-1, int MIN_PAD_LEN=0, bool USE_HASH_ID=false>
|
||||
class PSSR_MEM : public PSSR_MEM_BaseWithHashId<USE_HASH_ID>
|
||||
{
|
||||
virtual bool AllowRecovery() const {return ALLOW_RECOVERY;}
|
||||
virtual unsigned int SaltLen(unsigned int hashLen) const {return SALT_LEN < 0 ? hashLen : SALT_LEN;}
|
||||
virtual unsigned int MinPadLen(unsigned int hashLen) const {return MIN_PAD_LEN < 0 ? hashLen : MIN_PAD_LEN;}
|
||||
virtual const MaskGeneratingFunction & GetMGF() const {static MGF mgf; return mgf;}
|
||||
|
||||
public:
|
||||
static std::string StaticAlgorithmName() {return std::string(ALLOW_RECOVERY ? "PSSR-" : "PSS-") + MGF::StaticAlgorithmName();}
|
||||
};
|
||||
|
||||
//! <a href="http://www.weidai.com/scan-mirror/sig.html#sem_PSSR-MGF1">PSSR-MGF1</a>
|
||||
struct PSSR : public SignatureStandard
|
||||
{
|
||||
typedef PSSR_MEM<true> SignatureMessageEncodingMethod;
|
||||
};
|
||||
|
||||
//! <a href="http://www.weidai.com/scan-mirror/sig.html#sem_PSS-MGF1">PSS-MGF1</a>
|
||||
struct PSS : public SignatureStandard
|
||||
{
|
||||
typedef PSSR_MEM<false> SignatureMessageEncodingMethod;
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,122 @@
|
||||
// pubkey.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
#include "pubkey.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
void P1363_MGF1KDF2_Common(HashTransformation &hash, byte *output, unsigned int outputLength, const byte *input, unsigned int inputLength, bool mask, unsigned int counterStart)
|
||||
{
|
||||
ArraySink *sink;
|
||||
HashFilter filter(hash, sink = mask ? new ArrayXorSink(output, outputLength) : new ArraySink(output, outputLength));
|
||||
word32 counter = counterStart;
|
||||
while (sink->AvailableSize() > 0)
|
||||
{
|
||||
filter.Put(input, inputLength);
|
||||
filter.PutWord32(counter++);
|
||||
filter.MessageEnd();
|
||||
}
|
||||
}
|
||||
|
||||
bool PK_DeterministicSignatureMessageEncodingMethod::VerifyMessageRepresentative(
|
||||
HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
|
||||
byte *representative, unsigned int representativeBitLength) const
|
||||
{
|
||||
SecByteBlock computedRepresentative(BitsToBytes(representativeBitLength));
|
||||
ComputeMessageRepresentative(NullRNG(), NULL, 0, hash, hashIdentifier, messageEmpty, computedRepresentative, representativeBitLength);
|
||||
return memcmp(representative, computedRepresentative, computedRepresentative.size()) == 0;
|
||||
}
|
||||
|
||||
bool PK_RecoverableSignatureMessageEncodingMethod::VerifyMessageRepresentative(
|
||||
HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
|
||||
byte *representative, unsigned int representativeBitLength) const
|
||||
{
|
||||
SecByteBlock recoveredMessage(MaxRecoverableLength(representativeBitLength, hashIdentifier.second, hash.DigestSize()));
|
||||
DecodingResult result = RecoverMessageFromRepresentative(
|
||||
hash, hashIdentifier, messageEmpty, representative, representativeBitLength, recoveredMessage);
|
||||
return result.isValidCoding && result.messageLength == 0;
|
||||
}
|
||||
|
||||
void TF_SignerBase::InputRecoverableMessage(PK_MessageAccumulator &messageAccumulator, const byte *recoverableMessage, unsigned int recoverableMessageLength) const
|
||||
{
|
||||
PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
|
||||
const MessageEncodingInterface &mei = GetMessageEncodingInterface();
|
||||
unsigned int maxRecoverableLength = mei.MaxRecoverableLength(MessageRepresentativeBitLength(), GetHashIdentifier().second, ma.AccessHash().DigestSize());
|
||||
|
||||
if (maxRecoverableLength == 0)
|
||||
{throw NotImplemented("TF_SignerBase: this algorithm does not support messsage recovery or the key is too short");}
|
||||
if (recoverableMessageLength > maxRecoverableLength)
|
||||
throw InvalidArgument("TF_SignerBase: the recoverable message part is too long for the given key and algorithm");
|
||||
|
||||
ma.m_recoverableMessage.Assign(recoverableMessage, recoverableMessageLength);
|
||||
mei.ProcessRecoverableMessage(
|
||||
ma.AccessHash(),
|
||||
recoverableMessage, recoverableMessageLength,
|
||||
NULL, 0, ma.m_semisignature);
|
||||
}
|
||||
|
||||
unsigned int TF_SignerBase::SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart) const
|
||||
{
|
||||
PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
|
||||
SecByteBlock representative(MessageRepresentativeLength());
|
||||
GetMessageEncodingInterface().ComputeMessageRepresentative(rng,
|
||||
ma.m_recoverableMessage, ma.m_recoverableMessage.size(),
|
||||
ma.AccessHash(), GetHashIdentifier(), ma.m_empty,
|
||||
representative, MessageRepresentativeBitLength());
|
||||
ma.m_empty = true;
|
||||
|
||||
Integer r(representative, representative.size());
|
||||
unsigned int signatureLength = SignatureLength();
|
||||
GetTrapdoorFunctionInterface().CalculateRandomizedInverse(rng, r).Encode(signature, signatureLength);
|
||||
return signatureLength;
|
||||
}
|
||||
|
||||
void TF_VerifierBase::InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, unsigned int signatureLength) const
|
||||
{
|
||||
PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
|
||||
ma.m_representative.New(MessageRepresentativeLength());
|
||||
Integer x = GetTrapdoorFunctionInterface().ApplyFunction(Integer(signature, signatureLength));
|
||||
if (x.BitCount() > MessageRepresentativeBitLength())
|
||||
x = Integer::Zero(); // don't return false here to prevent timing attack
|
||||
x.Encode(ma.m_representative, ma.m_representative.size());
|
||||
}
|
||||
|
||||
bool TF_VerifierBase::VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const
|
||||
{
|
||||
PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
|
||||
bool result = GetMessageEncodingInterface().VerifyMessageRepresentative(
|
||||
ma.AccessHash(), GetHashIdentifier(), ma.m_empty, ma.m_representative, MessageRepresentativeBitLength());
|
||||
ma.m_empty = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
DecodingResult TF_VerifierBase::RecoverAndRestart(byte *recoveredMessage, PK_MessageAccumulator &messageAccumulator) const
|
||||
{
|
||||
PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
|
||||
DecodingResult result = GetMessageEncodingInterface().RecoverMessageFromRepresentative(
|
||||
ma.AccessHash(), GetHashIdentifier(), ma.m_empty, ma.m_representative, MessageRepresentativeBitLength(), recoveredMessage);
|
||||
ma.m_empty = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
DecodingResult TF_DecryptorBase::FixedLengthDecrypt(RandomNumberGenerator &rng, const byte *cipherText, byte *plainText) const
|
||||
{
|
||||
SecByteBlock paddedBlock(PaddedBlockByteLength());
|
||||
Integer x = GetTrapdoorFunctionInterface().CalculateInverse(rng, Integer(cipherText, FixedCiphertextLength()));
|
||||
if (x.ByteCount() > paddedBlock.size())
|
||||
x = Integer::Zero(); // don't return false here to prevent timing attack
|
||||
x.Encode(paddedBlock, paddedBlock.size());
|
||||
return GetMessageEncodingInterface().Unpad(paddedBlock, PaddedBlockBitLength(), plainText);
|
||||
}
|
||||
|
||||
void TF_EncryptorBase::Encrypt(RandomNumberGenerator &rng, const byte *plainText, unsigned int plainTextLength, byte *cipherText) const
|
||||
{
|
||||
if (plainTextLength > FixedMaxPlaintextLength())
|
||||
throw InvalidArgument(AlgorithmName() + ": message too long for this public key");
|
||||
|
||||
SecByteBlock paddedBlock(PaddedBlockByteLength());
|
||||
GetMessageEncodingInterface().Pad(rng, plainText, plainTextLength, paddedBlock, PaddedBlockBitLength());
|
||||
GetTrapdoorFunctionInterface().ApplyRandomizedFunction(rng, Integer(paddedBlock, paddedBlock.size())).Encode(cipherText, FixedCiphertextLength());
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,518 @@
|
||||
// queue.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.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 *begin, unsigned int length)
|
||||
{
|
||||
unsigned int l = STDMIN(length, MaxSize()-m_tail);
|
||||
memcpy(buf+m_tail, begin, 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 std::string &channel=BufferedTransformation::NULL_CHANNEL) const
|
||||
{
|
||||
unsigned int len = m_tail-m_head;
|
||||
target.ChannelPut(channel, buf+m_head, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
inline unsigned int CopyTo(BufferedTransformation &target, unsigned int copyMax, const std::string &channel=BufferedTransformation::NULL_CHANNEL) const
|
||||
{
|
||||
unsigned int len = STDMIN(copyMax, m_tail-m_head);
|
||||
target.ChannelPut(channel, 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, const std::string &channel=BufferedTransformation::NULL_CHANNEL)
|
||||
{
|
||||
unsigned int len = m_tail-m_head;
|
||||
target.ChannelPutModifiable(channel, buf+m_head, len);
|
||||
m_head = m_tail;
|
||||
return len;
|
||||
}
|
||||
|
||||
inline unsigned int TransferTo(BufferedTransformation &target, unsigned int transferMax, const std::string &channel=BufferedTransformation::NULL_CHANNEL)
|
||||
{
|
||||
unsigned int len = STDMIN(transferMax, m_tail-m_head);
|
||||
target.ChannelPutModifiable(channel, buf+m_head, len);
|
||||
m_head += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
inline unsigned int Skip(unsigned int skipMax)
|
||||
{
|
||||
unsigned int len = STDMIN(skipMax, m_tail-m_head);
|
||||
m_head += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
inline byte operator[](unsigned int i) const
|
||||
{
|
||||
return buf[m_head+i];
|
||||
}
|
||||
|
||||
ByteQueueNode *next;
|
||||
|
||||
SecByteBlock buf;
|
||||
unsigned int m_head, m_tail;
|
||||
};
|
||||
|
||||
// ********************************************************
|
||||
|
||||
ByteQueue::ByteQueue(unsigned int m_nodeSize)
|
||||
: m_nodeSize(m_nodeSize), m_lazyLength(0)
|
||||
{
|
||||
m_head = m_tail = new ByteQueueNode(m_nodeSize);
|
||||
}
|
||||
|
||||
ByteQueue::ByteQueue(const ByteQueue ©)
|
||||
{
|
||||
CopyFrom(copy);
|
||||
}
|
||||
|
||||
void ByteQueue::CopyFrom(const ByteQueue ©)
|
||||
{
|
||||
m_lazyLength = 0;
|
||||
m_nodeSize = copy.m_nodeSize;
|
||||
m_head = m_tail = new ByteQueueNode(*copy.m_head);
|
||||
|
||||
for (ByteQueueNode *current=copy.m_head->next; current; current=current->next)
|
||||
{
|
||||
m_tail->next = new ByteQueueNode(*current);
|
||||
m_tail = m_tail->next;
|
||||
}
|
||||
|
||||
m_tail->next = NULL;
|
||||
|
||||
Put(copy.m_lazyString, copy.m_lazyLength);
|
||||
}
|
||||
|
||||
ByteQueue::~ByteQueue()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void ByteQueue::Destroy()
|
||||
{
|
||||
ByteQueueNode *next;
|
||||
|
||||
for (ByteQueueNode *current=m_head; current; current=next)
|
||||
{
|
||||
next=current->next;
|
||||
delete current;
|
||||
}
|
||||
}
|
||||
|
||||
void ByteQueue::IsolatedInitialize(const NameValuePairs ¶meters)
|
||||
{
|
||||
m_nodeSize = parameters.GetIntValueWithDefault("NodeSize", 256);
|
||||
Clear();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
unsigned int ByteQueue::Put2(const byte *inString, unsigned int length, int messageEnd, bool blocking)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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::UndoLazyPut(unsigned int size)
|
||||
{
|
||||
if (m_lazyLength < size)
|
||||
throw InvalidArgument("ByteQueue: size specified for UndoLazyPut is too large");
|
||||
|
||||
m_lazyLength -= size;
|
||||
}
|
||||
|
||||
void ByteQueue::FinalizeLazyPut()
|
||||
{
|
||||
unsigned int len = m_lazyLength;
|
||||
m_lazyLength = 0;
|
||||
if (len)
|
||||
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 int ByteQueue::TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel, bool blocking)
|
||||
{
|
||||
if (blocking)
|
||||
{
|
||||
unsigned long bytesLeft = transferBytes;
|
||||
for (ByteQueueNode *current=m_head; bytesLeft && current; current=current->next)
|
||||
bytesLeft -= current->TransferTo(target, bytesLeft, channel);
|
||||
CleanupUsedNodes();
|
||||
|
||||
unsigned int len = (unsigned int)STDMIN(bytesLeft, (unsigned long)m_lazyLength);
|
||||
if (len)
|
||||
{
|
||||
target.ChannelPut(channel, m_lazyString, len);
|
||||
m_lazyString += len;
|
||||
m_lazyLength -= len;
|
||||
bytesLeft -= len;
|
||||
}
|
||||
transferBytes -= bytesLeft;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Walker walker(*this);
|
||||
unsigned int blockedBytes = walker.TransferTo2(target, transferBytes, channel, blocking);
|
||||
Skip(transferBytes);
|
||||
return blockedBytes;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int ByteQueue::CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end, const std::string &channel, bool blocking) const
|
||||
{
|
||||
Walker walker(*this);
|
||||
walker.Skip(begin);
|
||||
unsigned long transferBytes = end-begin;
|
||||
unsigned int blockedBytes = walker.TransferTo2(target, transferBytes, channel, blocking);
|
||||
begin += transferBytes;
|
||||
return blockedBytes;
|
||||
}
|
||||
|
||||
void ByteQueue::Unget(byte inByte)
|
||||
{
|
||||
Unget(&inByte, 1);
|
||||
}
|
||||
|
||||
void ByteQueue::Unget(const byte *inString, unsigned int length)
|
||||
{
|
||||
// TODO: make this more efficient
|
||||
ByteQueueNode *newHead = new ByteQueueNode(length);
|
||||
newHead->next = m_head;
|
||||
m_head = newHead;
|
||||
m_head->Put(inString, length);
|
||||
}
|
||||
|
||||
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::CreatePutSpace(unsigned int &size)
|
||||
{
|
||||
if (m_lazyLength > 0)
|
||||
FinalizeLazyPut();
|
||||
|
||||
if (m_tail->m_tail == m_tail->MaxSize())
|
||||
{
|
||||
m_tail->next = new ByteQueueNode(size < m_nodeSize ? m_nodeSize : STDMAX(m_nodeSize, 1024U));
|
||||
m_tail = m_tail->next;
|
||||
}
|
||||
|
||||
size = m_tail->MaxSize() - m_tail->m_tail;
|
||||
return m_tail->buf + m_tail->m_tail;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// ********************************************************
|
||||
|
||||
void ByteQueue::Walker::IsolatedInitialize(const NameValuePairs ¶meters)
|
||||
{
|
||||
m_node = m_queue.m_head;
|
||||
m_position = 0;
|
||||
m_offset = 0;
|
||||
m_lazyString = m_queue.m_lazyString;
|
||||
m_lazyLength = m_queue.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 int ByteQueue::Walker::TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel, bool blocking)
|
||||
{
|
||||
unsigned long bytesLeft = transferBytes;
|
||||
unsigned int blockedBytes = 0;
|
||||
|
||||
while (m_node)
|
||||
{
|
||||
unsigned int len = STDMIN(bytesLeft, (unsigned long)m_node->CurrentSize()-m_offset);
|
||||
blockedBytes = target.ChannelPut2(channel, m_node->buf+m_node->m_head+m_offset, len, 0, blocking);
|
||||
|
||||
if (blockedBytes)
|
||||
goto done;
|
||||
|
||||
m_position += len;
|
||||
bytesLeft -= len;
|
||||
|
||||
if (!bytesLeft)
|
||||
{
|
||||
m_offset += len;
|
||||
goto done;
|
||||
}
|
||||
|
||||
m_node = m_node->next;
|
||||
m_offset = 0;
|
||||
}
|
||||
|
||||
if (bytesLeft && m_lazyLength)
|
||||
{
|
||||
unsigned int len = (unsigned int)STDMIN(bytesLeft, (unsigned long)m_lazyLength);
|
||||
unsigned int blockedBytes = target.ChannelPut2(channel, m_lazyString, len, 0, blocking);
|
||||
if (blockedBytes)
|
||||
goto done;
|
||||
|
||||
m_lazyString += len;
|
||||
m_lazyLength -= len;
|
||||
bytesLeft -= len;
|
||||
}
|
||||
|
||||
done:
|
||||
transferBytes -= bytesLeft;
|
||||
return blockedBytes;
|
||||
}
|
||||
|
||||
unsigned int ByteQueue::Walker::CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end, const std::string &channel, bool blocking) const
|
||||
{
|
||||
Walker walker(*this);
|
||||
walker.Skip(begin);
|
||||
unsigned long transferBytes = end-begin;
|
||||
unsigned int blockedBytes = walker.TransferTo2(target, transferBytes, channel, blocking);
|
||||
begin += transferBytes;
|
||||
return blockedBytes;
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -0,0 +1,128 @@
|
||||
// specification file for an unlimited queue for storing bytes
|
||||
|
||||
#ifndef CRYPTOPP_QUEUE_H
|
||||
#define CRYPTOPP_QUEUE_H
|
||||
|
||||
#include "simple.h"
|
||||
//#include <algorithm>
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
/** The queue is implemented as a linked list of byte arrays, but you don't need to
|
||||
know about that. So just ignore this next line. :) */
|
||||
class ByteQueueNode;
|
||||
|
||||
//! Byte Queue
|
||||
class ByteQueue : public Bufferless<BufferedTransformation>
|
||||
{
|
||||
public:
|
||||
ByteQueue(unsigned int m_nodeSize=256);
|
||||
ByteQueue(const ByteQueue ©);
|
||||
~ByteQueue();
|
||||
|
||||
unsigned long MaxRetrievable() const
|
||||
{return CurrentSize();}
|
||||
bool AnyRetrievable() const
|
||||
{return !IsEmpty();}
|
||||
|
||||
void IsolatedInitialize(const NameValuePairs ¶meters);
|
||||
byte * CreatePutSpace(unsigned int &size);
|
||||
unsigned int Put2(const byte *inString, unsigned int length, int messageEnd, bool blocking);
|
||||
|
||||
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 int TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel=NULL_CHANNEL, bool blocking=true);
|
||||
unsigned int CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end=ULONG_MAX, const std::string &channel=NULL_CHANNEL, bool blocking=true) const;
|
||||
|
||||
// these member functions are not inherited
|
||||
void SetNodeSize(unsigned int nodeSize) {m_nodeSize = nodeSize;}
|
||||
|
||||
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;
|
||||
|
||||
void LazyPut(const byte *inString, unsigned int size);
|
||||
void UndoLazyPut(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 InputRejecting<BufferedTransformation>
|
||||
{
|
||||
public:
|
||||
Walker(const ByteQueue &queue)
|
||||
: m_queue(queue) {Initialize();}
|
||||
|
||||
unsigned long GetCurrentPosition() {return m_position;}
|
||||
|
||||
unsigned long MaxRetrievable() const
|
||||
{return m_queue.CurrentSize() - m_position;}
|
||||
|
||||
void IsolatedInitialize(const NameValuePairs ¶meters);
|
||||
|
||||
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 int TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel=NULL_CHANNEL, bool blocking=true);
|
||||
unsigned int CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end=ULONG_MAX, const std::string &channel=NULL_CHANNEL, bool blocking=true) const;
|
||||
|
||||
private:
|
||||
const ByteQueue &m_queue;
|
||||
const ByteQueueNode *m_node;
|
||||
unsigned long m_position;
|
||||
unsigned int m_offset;
|
||||
const byte *m_lazyString;
|
||||
unsigned int m_lazyLength;
|
||||
};
|
||||
|
||||
friend class Walker;
|
||||
|
||||
private:
|
||||
void CleanupUsedNodes();
|
||||
void CopyFrom(const ByteQueue ©);
|
||||
void Destroy();
|
||||
|
||||
unsigned int m_nodeSize;
|
||||
ByteQueueNode *m_head, *m_tail;
|
||||
const byte *m_lazyString;
|
||||
unsigned int m_lazyLength;
|
||||
};
|
||||
|
||||
//! use this to make sure LazyPut is finalized in event of exception
|
||||
class LazyPutter
|
||||
{
|
||||
public:
|
||||
LazyPutter(ByteQueue &bq, const byte *inString, unsigned int size)
|
||||
: m_bq(bq) {bq.LazyPut(inString, size);}
|
||||
~LazyPutter()
|
||||
{try {m_bq.FinalizeLazyPut();} catch(...) {}}
|
||||
private:
|
||||
ByteQueue &m_bq;
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
NAMESPACE_BEGIN(std)
|
||||
template<> inline void swap(CryptoPP::ByteQueue &a, CryptoPP::ByteQueue &b)
|
||||
{
|
||||
a.swap(b);
|
||||
}
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,100 @@
|
||||
// randpool.cpp - written and placed in the public domain by Wei Dai
|
||||
// The algorithm in this module comes from PGP's randpool.c
|
||||
|
||||
#include "pch.h"
|
||||
#include "randpool.h"
|
||||
#include "mdc.h"
|
||||
#include "sha.h"
|
||||
#include "modes.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
typedef MDC<SHA> RandomPoolCipher;
|
||||
|
||||
RandomPool::RandomPool(unsigned int poolSize)
|
||||
: pool(poolSize), key(RandomPoolCipher::DEFAULT_KEYLENGTH)
|
||||
{
|
||||
assert(poolSize > key.size());
|
||||
|
||||
addPos=0;
|
||||
getPos=poolSize;
|
||||
memset(pool, 0, poolSize);
|
||||
memset(key, 0, key.size());
|
||||
}
|
||||
|
||||
void RandomPool::Stir()
|
||||
{
|
||||
CFB_Mode<RandomPoolCipher>::Encryption cipher;
|
||||
|
||||
for (int i=0; i<2; i++)
|
||||
{
|
||||
cipher.SetKeyWithIV(key, key.size(), pool.end()-cipher.IVSize());
|
||||
cipher.ProcessString(pool, pool.size());
|
||||
memcpy(key, pool, key.size());
|
||||
}
|
||||
|
||||
addPos = 0;
|
||||
getPos = key.size();
|
||||
}
|
||||
|
||||
unsigned int RandomPool::Put2(const byte *inString, unsigned int length, int messageEnd, bool blocking)
|
||||
{
|
||||
unsigned t;
|
||||
|
||||
while (length > (t = pool.size() - addPos))
|
||||
{
|
||||
xorbuf(pool+addPos, inString, t);
|
||||
inString += t;
|
||||
length -= t;
|
||||
Stir();
|
||||
}
|
||||
|
||||
if (length)
|
||||
{
|
||||
xorbuf(pool+addPos, inString, length);
|
||||
addPos += length;
|
||||
getPos = pool.size(); // Force stir on get
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int RandomPool::TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel, bool blocking)
|
||||
{
|
||||
if (!blocking)
|
||||
throw NotImplemented("RandomPool: nonblocking transfer is not implemented by this object");
|
||||
|
||||
unsigned int t;
|
||||
unsigned long size = transferBytes;
|
||||
|
||||
while (size > (t = pool.size() - getPos))
|
||||
{
|
||||
target.ChannelPut(channel, pool+getPos, t);
|
||||
size -= t;
|
||||
Stir();
|
||||
}
|
||||
|
||||
if (size)
|
||||
{
|
||||
target.ChannelPut(channel, pool+getPos, size);
|
||||
getPos += size;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
byte RandomPool::GenerateByte()
|
||||
{
|
||||
if (getPos == pool.size())
|
||||
Stir();
|
||||
|
||||
return pool[getPos++];
|
||||
}
|
||||
|
||||
void RandomPool::GenerateBlock(byte *outString, unsigned int size)
|
||||
{
|
||||
ArraySink sink(outString, size);
|
||||
TransferTo(sink, size);
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -0,0 +1,46 @@
|
||||
#ifndef CRYPTOPP_RANDPOOL_H
|
||||
#define CRYPTOPP_RANDPOOL_H
|
||||
|
||||
#include "cryptlib.h"
|
||||
#include "filters.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
//! Randomness Pool
|
||||
/*! This class can be used to generate
|
||||
pseudorandom bytes after seeding the pool with
|
||||
the Put() methods */
|
||||
class RandomPool : public RandomNumberGenerator,
|
||||
public Bufferless<BufferedTransformation>
|
||||
{
|
||||
public:
|
||||
//! poolSize must be greater than 16
|
||||
RandomPool(unsigned int poolSize=384);
|
||||
|
||||
unsigned int Put2(const byte *begin, unsigned int, int messageEnd, bool blocking);
|
||||
|
||||
bool AnyRetrievable() const {return true;}
|
||||
unsigned long MaxRetrievable() const {return ULONG_MAX;}
|
||||
|
||||
unsigned int TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel=NULL_CHANNEL, bool blocking=true);
|
||||
unsigned int CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end=ULONG_MAX, const std::string &channel=NULL_CHANNEL, bool blocking=true) const
|
||||
{
|
||||
throw NotImplemented("RandomPool: CopyRangeTo2() is not supported by this store");
|
||||
}
|
||||
|
||||
byte GenerateByte();
|
||||
void GenerateBlock(byte *output, unsigned int size);
|
||||
|
||||
void IsolatedInitialize(const NameValuePairs ¶meters) {}
|
||||
|
||||
protected:
|
||||
void Stir();
|
||||
|
||||
private:
|
||||
SecByteBlock pool, key;
|
||||
unsigned int addPos, getPos;
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,78 @@
|
||||
#ifndef CRYPTOPP_RNG_H
|
||||
#define CRYPTOPP_RNG_H
|
||||
|
||||
#include "cryptlib.h"
|
||||
#include "filters.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
//! linear congruential generator
|
||||
/*! originally by William S. England, do not use for cryptographic purposes */
|
||||
class LC_RNG : public RandomNumberGenerator
|
||||
{
|
||||
public:
|
||||
LC_RNG(word32 init_seed)
|
||||
: seed(init_seed) {}
|
||||
|
||||
byte GenerateByte();
|
||||
|
||||
word32 GetSeed() {return seed;}
|
||||
|
||||
private:
|
||||
word32 seed;
|
||||
|
||||
static const word32 m;
|
||||
static const word32 q;
|
||||
static const word16 a;
|
||||
static const word16 r;
|
||||
};
|
||||
|
||||
//! RNG derived from ANSI X9.17 Appendix C
|
||||
|
||||
class X917RNG : public RandomNumberGenerator
|
||||
{
|
||||
public:
|
||||
// cipher will be deleted by destructor, deterministicTimeVector = 0 means obtain time vector from system
|
||||
X917RNG(BlockTransformation *cipher, const byte *seed, unsigned long deterministicTimeVector = 0);
|
||||
|
||||
byte GenerateByte();
|
||||
|
||||
private:
|
||||
member_ptr<BlockTransformation> cipher;
|
||||
const int S; // blocksize of cipher
|
||||
SecByteBlock dtbuf; // buffer for enciphered timestamp
|
||||
SecByteBlock randseed, randbuf;
|
||||
int randbuf_counter; // # of unused bytes left in randbuf
|
||||
unsigned long m_deterministicTimeVector;
|
||||
};
|
||||
|
||||
/** This class implements Maurer's Universal Statistical Test for Random Bit Generators
|
||||
it is intended for measuring the randomness of *PHYSICAL* RNGs.
|
||||
For more details see his paper in Journal of Cryptology, 1992. */
|
||||
|
||||
class MaurerRandomnessTest : public Sink
|
||||
{
|
||||
public:
|
||||
MaurerRandomnessTest();
|
||||
|
||||
void Put(byte inByte);
|
||||
void Put(const byte *inString, unsigned int length);
|
||||
|
||||
// BytesNeeded() returns how many more bytes of input is needed by the test
|
||||
// GetTestValue() should not be called before BytesNeeded()==0
|
||||
unsigned int BytesNeeded() const {return n >= (Q+K) ? 0 : Q+K-n;}
|
||||
|
||||
// returns a number between 0.0 and 1.0, describing the quality of the
|
||||
// random numbers entered
|
||||
double GetTestValue() const;
|
||||
|
||||
private:
|
||||
enum {L=8, V=256, Q=2000, K=2000};
|
||||
double sum;
|
||||
unsigned int n;
|
||||
unsigned int tab[V];
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,277 @@
|
||||
// rsa.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
#include "rsa.h"
|
||||
#include "asn.h"
|
||||
#include "oids.h"
|
||||
#include "modarith.h"
|
||||
#include "nbtheory.h"
|
||||
#include "sha.h"
|
||||
#include "algparam.h"
|
||||
#include "fips140.h"
|
||||
|
||||
#ifndef NDEBUG
|
||||
#include "pssr.h"
|
||||
#endif
|
||||
|
||||
#include "oaep.cpp"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
#ifndef NDEBUG
|
||||
void RSA_TestInstantiations()
|
||||
{
|
||||
RSASS<PKCS1v15, SHA>::Verifier x1(1, 1);
|
||||
RSASS<PKCS1v15, SHA>::Signer x2(NullRNG(), 1);
|
||||
RSASS<PKCS1v15, SHA>::Verifier x3(x2);
|
||||
RSASS<PKCS1v15, SHA>::Verifier x4(x2.GetKey());
|
||||
RSASS<PSS, SHA>::Verifier x5(x3);
|
||||
#ifndef __MWERKS__
|
||||
RSASS<PSSR, SHA>::Signer x6 = x2;
|
||||
x3 = x2;
|
||||
x6 = x2;
|
||||
#endif
|
||||
RSAES<PKCS1v15>::Encryptor x7(x2);
|
||||
#ifndef __GNUC__
|
||||
RSAES<PKCS1v15>::Encryptor x8(x3);
|
||||
#endif
|
||||
RSAES<OAEP<SHA> >::Encryptor x9(x2);
|
||||
|
||||
x4 = x2.GetKey();
|
||||
}
|
||||
#endif
|
||||
|
||||
template class OAEP<SHA>;
|
||||
|
||||
OID RSAFunction::GetAlgorithmID() const
|
||||
{
|
||||
return ASN1::rsaEncryption();
|
||||
}
|
||||
|
||||
void RSAFunction::BERDecodeKey(BufferedTransformation &bt)
|
||||
{
|
||||
BERSequenceDecoder seq(bt);
|
||||
m_n.BERDecode(seq);
|
||||
m_e.BERDecode(seq);
|
||||
seq.MessageEnd();
|
||||
}
|
||||
|
||||
void RSAFunction::DEREncodeKey(BufferedTransformation &bt) const
|
||||
{
|
||||
DERSequenceEncoder seq(bt);
|
||||
m_n.DEREncode(seq);
|
||||
m_e.DEREncode(seq);
|
||||
seq.MessageEnd();
|
||||
}
|
||||
|
||||
Integer RSAFunction::ApplyFunction(const Integer &x) const
|
||||
{
|
||||
DoQuickSanityCheck();
|
||||
return a_exp_b_mod_c(x, m_e, m_n);
|
||||
}
|
||||
|
||||
bool RSAFunction::Validate(RandomNumberGenerator &rng, unsigned int level) const
|
||||
{
|
||||
bool pass = true;
|
||||
pass = pass && m_n > Integer::One() && m_n.IsOdd();
|
||||
pass = pass && m_e > Integer::One() && m_e.IsOdd() && m_e < m_n;
|
||||
return pass;
|
||||
}
|
||||
|
||||
bool RSAFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
|
||||
{
|
||||
return GetValueHelper(this, name, valueType, pValue).Assignable()
|
||||
CRYPTOPP_GET_FUNCTION_ENTRY(Modulus)
|
||||
CRYPTOPP_GET_FUNCTION_ENTRY(PublicExponent)
|
||||
;
|
||||
}
|
||||
|
||||
void RSAFunction::AssignFrom(const NameValuePairs &source)
|
||||
{
|
||||
AssignFromHelper(this, source)
|
||||
CRYPTOPP_SET_FUNCTION_ENTRY(Modulus)
|
||||
CRYPTOPP_SET_FUNCTION_ENTRY(PublicExponent)
|
||||
;
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
|
||||
class RSAPrimeSelector : public PrimeSelector
|
||||
{
|
||||
public:
|
||||
RSAPrimeSelector(const Integer &e) : m_e(e) {}
|
||||
bool IsAcceptable(const Integer &candidate) const {return RelativelyPrime(m_e, candidate-Integer::One());}
|
||||
Integer m_e;
|
||||
};
|
||||
|
||||
void InvertibleRSAFunction::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg)
|
||||
{
|
||||
int modulusSize = 2048;
|
||||
alg.GetIntValue("ModulusSize", modulusSize) || alg.GetIntValue("KeySize", modulusSize);
|
||||
|
||||
if (modulusSize < 16)
|
||||
throw InvalidArgument("InvertibleRSAFunction: specified modulus size is too small");
|
||||
|
||||
m_e = alg.GetValueWithDefault("PublicExponent", Integer(17));
|
||||
|
||||
if (m_e < 3 || m_e.IsEven())
|
||||
throw InvalidArgument("InvertibleRSAFunction: invalid public exponent");
|
||||
|
||||
RSAPrimeSelector selector(m_e);
|
||||
const NameValuePairs &primeParam = MakeParametersForTwoPrimesOfEqualSize(modulusSize)
|
||||
("PointerToPrimeSelector", selector.GetSelectorPointer());
|
||||
m_p.GenerateRandom(rng, primeParam);
|
||||
m_q.GenerateRandom(rng, primeParam);
|
||||
|
||||
m_d = EuclideanMultiplicativeInverse(m_e, LCM(m_p-1, m_q-1));
|
||||
assert(m_d.IsPositive());
|
||||
|
||||
m_dp = m_d % (m_p-1);
|
||||
m_dq = m_d % (m_q-1);
|
||||
m_n = m_p * m_q;
|
||||
m_u = m_q.InverseMod(m_p);
|
||||
|
||||
if (FIPS_140_2_ComplianceEnabled())
|
||||
{
|
||||
RSASS<PKCS1v15, SHA>::Signer signer(*this);
|
||||
RSASS<PKCS1v15, SHA>::Verifier verifier(signer);
|
||||
SignaturePairwiseConsistencyTest_FIPS_140_Only(signer, verifier);
|
||||
|
||||
RSAES<OAEP<SHA> >::Decryptor decryptor(*this);
|
||||
RSAES<OAEP<SHA> >::Encryptor encryptor(decryptor);
|
||||
EncryptionPairwiseConsistencyTest_FIPS_140_Only(encryptor, decryptor);
|
||||
}
|
||||
}
|
||||
|
||||
void InvertibleRSAFunction::Initialize(RandomNumberGenerator &rng, unsigned int keybits, const Integer &e)
|
||||
{
|
||||
GenerateRandom(rng, MakeParameters("ModulusSize", (int)keybits)("PublicExponent", e+e.IsEven()));
|
||||
}
|
||||
|
||||
void InvertibleRSAFunction::Initialize(const Integer &n, const Integer &e, const Integer &d)
|
||||
{
|
||||
m_n = n;
|
||||
m_e = e;
|
||||
m_d = d;
|
||||
|
||||
Integer r = --(d*e);
|
||||
while (r.IsEven())
|
||||
r >>= 1;
|
||||
|
||||
ModularArithmetic modn(n);
|
||||
for (Integer i = 2; ; ++i)
|
||||
{
|
||||
Integer a = modn.Exponentiate(i, r);
|
||||
if (a == 1)
|
||||
continue;
|
||||
Integer b;
|
||||
while (a != -1)
|
||||
{
|
||||
b = modn.Square(a);
|
||||
if (b == 1)
|
||||
{
|
||||
m_p = GCD(a-1, n);
|
||||
m_q = n/m_p;
|
||||
m_dp = m_d % (m_p-1);
|
||||
m_dq = m_d % (m_q-1);
|
||||
m_u = m_q.InverseMod(m_p);
|
||||
return;
|
||||
}
|
||||
a = b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InvertibleRSAFunction::BERDecodeKey(BufferedTransformation &bt)
|
||||
{
|
||||
BERSequenceDecoder privateKey(bt);
|
||||
word32 version;
|
||||
BERDecodeUnsigned<word32>(privateKey, version, INTEGER, 0, 0); // check version
|
||||
m_n.BERDecode(privateKey);
|
||||
m_e.BERDecode(privateKey);
|
||||
m_d.BERDecode(privateKey);
|
||||
m_p.BERDecode(privateKey);
|
||||
m_q.BERDecode(privateKey);
|
||||
m_dp.BERDecode(privateKey);
|
||||
m_dq.BERDecode(privateKey);
|
||||
m_u.BERDecode(privateKey);
|
||||
privateKey.MessageEnd();
|
||||
}
|
||||
|
||||
void InvertibleRSAFunction::DEREncodeKey(BufferedTransformation &bt) const
|
||||
{
|
||||
DERSequenceEncoder privateKey(bt);
|
||||
DEREncodeUnsigned<word32>(privateKey, 0); // version
|
||||
m_n.DEREncode(privateKey);
|
||||
m_e.DEREncode(privateKey);
|
||||
m_d.DEREncode(privateKey);
|
||||
m_p.DEREncode(privateKey);
|
||||
m_q.DEREncode(privateKey);
|
||||
m_dp.DEREncode(privateKey);
|
||||
m_dq.DEREncode(privateKey);
|
||||
m_u.DEREncode(privateKey);
|
||||
privateKey.MessageEnd();
|
||||
}
|
||||
|
||||
Integer InvertibleRSAFunction::CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const
|
||||
{
|
||||
DoQuickSanityCheck();
|
||||
ModularArithmetic modn(m_n);
|
||||
Integer r(rng, Integer::One(), m_n - Integer::One());
|
||||
Integer re = modn.Exponentiate(r, m_e);
|
||||
re = modn.Multiply(re, x); // blind
|
||||
// here we follow the notation of PKCS #1 and let u=q inverse mod p
|
||||
// but in ModRoot, u=p inverse mod q, so we reverse the order of p and q
|
||||
Integer y = ModularRoot(re, m_dq, m_dp, m_q, m_p, m_u);
|
||||
y = modn.Divide(y, r); // unblind
|
||||
if (modn.Exponentiate(y, m_e) != x) // check
|
||||
throw Exception(Exception::OTHER_ERROR, "InvertibleRSAFunction: computational error during private key operation");
|
||||
return y;
|
||||
}
|
||||
|
||||
bool InvertibleRSAFunction::Validate(RandomNumberGenerator &rng, unsigned int level) const
|
||||
{
|
||||
bool pass = RSAFunction::Validate(rng, level);
|
||||
pass = pass && m_p > Integer::One() && m_p.IsOdd() && m_p < m_n;
|
||||
pass = pass && m_q > Integer::One() && m_q.IsOdd() && m_q < m_n;
|
||||
pass = pass && m_d > Integer::One() && m_d.IsOdd() && m_d < m_n;
|
||||
pass = pass && m_dp > Integer::One() && m_dp.IsOdd() && m_dp < m_p;
|
||||
pass = pass && m_dq > Integer::One() && m_dq.IsOdd() && m_dq < m_q;
|
||||
pass = pass && m_u.IsPositive() && m_u < m_p;
|
||||
if (level >= 1)
|
||||
{
|
||||
pass = pass && m_p * m_q == m_n;
|
||||
pass = pass && m_e*m_d % LCM(m_p-1, m_q-1) == 1;
|
||||
pass = pass && m_dp == m_d%(m_p-1) && m_dq == m_d%(m_q-1);
|
||||
pass = pass && m_u * m_q % m_p == 1;
|
||||
}
|
||||
if (level >= 2)
|
||||
pass = pass && VerifyPrime(rng, m_p, level-2) && VerifyPrime(rng, m_q, level-2);
|
||||
return pass;
|
||||
}
|
||||
|
||||
bool InvertibleRSAFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
|
||||
{
|
||||
return GetValueHelper<RSAFunction>(this, name, valueType, pValue).Assignable()
|
||||
CRYPTOPP_GET_FUNCTION_ENTRY(Prime1)
|
||||
CRYPTOPP_GET_FUNCTION_ENTRY(Prime2)
|
||||
CRYPTOPP_GET_FUNCTION_ENTRY(PrivateExponent)
|
||||
CRYPTOPP_GET_FUNCTION_ENTRY(ModPrime1PrivateExponent)
|
||||
CRYPTOPP_GET_FUNCTION_ENTRY(ModPrime2PrivateExponent)
|
||||
CRYPTOPP_GET_FUNCTION_ENTRY(MultiplicativeInverseOfPrime2ModPrime1)
|
||||
;
|
||||
}
|
||||
|
||||
void InvertibleRSAFunction::AssignFrom(const NameValuePairs &source)
|
||||
{
|
||||
AssignFromHelper<RSAFunction>(this, source)
|
||||
CRYPTOPP_SET_FUNCTION_ENTRY(Prime1)
|
||||
CRYPTOPP_SET_FUNCTION_ENTRY(Prime2)
|
||||
CRYPTOPP_SET_FUNCTION_ENTRY(PrivateExponent)
|
||||
CRYPTOPP_SET_FUNCTION_ENTRY(ModPrime1PrivateExponent)
|
||||
CRYPTOPP_SET_FUNCTION_ENTRY(ModPrime2PrivateExponent)
|
||||
CRYPTOPP_SET_FUNCTION_ENTRY(MultiplicativeInverseOfPrime2ModPrime1)
|
||||
;
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -0,0 +1,143 @@
|
||||
#ifndef CRYPTOPP_RSA_H
|
||||
#define CRYPTOPP_RSA_H
|
||||
|
||||
/** \file
|
||||
This file contains classes that implement the RSA
|
||||
ciphers and signature schemes as defined in PKCS #1 v2.0.
|
||||
*/
|
||||
|
||||
#include "pkcspad.h"
|
||||
#include "oaep.h"
|
||||
#include "integer.h"
|
||||
#include "asn.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
//! .
|
||||
class RSAFunction : public TrapdoorFunction, public X509PublicKey
|
||||
{
|
||||
typedef RSAFunction ThisClass;
|
||||
|
||||
public:
|
||||
void Initialize(const Integer &n, const Integer &e)
|
||||
{m_n = n; m_e = e;}
|
||||
|
||||
// X509PublicKey
|
||||
OID GetAlgorithmID() const;
|
||||
void BERDecodeKey(BufferedTransformation &bt);
|
||||
void DEREncodeKey(BufferedTransformation &bt) const;
|
||||
|
||||
// CryptoMaterial
|
||||
bool Validate(RandomNumberGenerator &rng, unsigned int level) const;
|
||||
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
|
||||
void AssignFrom(const NameValuePairs &source);
|
||||
|
||||
// TrapdoorFunction
|
||||
Integer ApplyFunction(const Integer &x) const;
|
||||
Integer PreimageBound() const {return m_n;}
|
||||
Integer ImageBound() const {return m_n;}
|
||||
|
||||
// non-derived
|
||||
const Integer & GetModulus() const {return m_n;}
|
||||
const Integer & GetPublicExponent() const {return m_e;}
|
||||
|
||||
void SetModulus(const Integer &n) {m_n = n;}
|
||||
void SetPublicExponent(const Integer &e) {m_e = e;}
|
||||
|
||||
protected:
|
||||
Integer m_n, m_e;
|
||||
};
|
||||
|
||||
//! .
|
||||
class InvertibleRSAFunction : public RSAFunction, public TrapdoorFunctionInverse, public PKCS8PrivateKey
|
||||
{
|
||||
typedef InvertibleRSAFunction ThisClass;
|
||||
|
||||
public:
|
||||
void Initialize(RandomNumberGenerator &rng, unsigned int modulusBits, const Integer &e = 17);
|
||||
void Initialize(const Integer &n, const Integer &e, const Integer &d, const Integer &p, const Integer &q, const Integer &dp, const Integer &dq, const Integer &u)
|
||||
{m_n = n; m_e = e; m_d = d; m_p = p; m_q = q; m_dp = dp; m_dq = dq; m_u = u;}
|
||||
//! factor n given private exponent
|
||||
void Initialize(const Integer &n, const Integer &e, const Integer &d);
|
||||
|
||||
// PKCS8PrivateKey
|
||||
void BERDecode(BufferedTransformation &bt)
|
||||
{PKCS8PrivateKey::BERDecode(bt);}
|
||||
void DEREncode(BufferedTransformation &bt) const
|
||||
{PKCS8PrivateKey::DEREncode(bt);}
|
||||
void BERDecodeKey(BufferedTransformation &bt);
|
||||
void DEREncodeKey(BufferedTransformation &bt) const;
|
||||
|
||||
// TrapdoorFunctionInverse
|
||||
Integer CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const;
|
||||
|
||||
// GeneratableCryptoMaterial
|
||||
bool Validate(RandomNumberGenerator &rng, unsigned int level) const;
|
||||
/*! parameters: (ModulusSize, PublicExponent (default 17)) */
|
||||
void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg);
|
||||
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
|
||||
void AssignFrom(const NameValuePairs &source);
|
||||
|
||||
// non-derived interface
|
||||
const Integer& GetPrime1() const {return m_p;}
|
||||
const Integer& GetPrime2() const {return m_q;}
|
||||
const Integer& GetPrivateExponent() const {return m_d;}
|
||||
const Integer& GetModPrime1PrivateExponent() const {return m_dp;}
|
||||
const Integer& GetModPrime2PrivateExponent() const {return m_dq;}
|
||||
const Integer& GetMultiplicativeInverseOfPrime2ModPrime1() const {return m_u;}
|
||||
|
||||
void SetPrime1(const Integer &p) {m_p = p;}
|
||||
void SetPrime2(const Integer &q) {m_q = q;}
|
||||
void SetPrivateExponent(const Integer &d) {m_d = d;}
|
||||
void SetModPrime1PrivateExponent(const Integer &dp) {m_dp = dp;}
|
||||
void SetModPrime2PrivateExponent(const Integer &dq) {m_dq = dq;}
|
||||
void SetMultiplicativeInverseOfPrime2ModPrime1(const Integer &u) {m_u = u;}
|
||||
|
||||
protected:
|
||||
virtual void DEREncodeOptionalAttributes(BufferedTransformation &bt) const {}
|
||||
virtual void BERDecodeOptionalAttributes(BufferedTransformation &bt) {}
|
||||
|
||||
Integer m_d, m_p, m_q, m_dp, m_dq, m_u;
|
||||
};
|
||||
|
||||
//! .
|
||||
struct RSA
|
||||
{
|
||||
static std::string StaticAlgorithmName() {return "RSA";}
|
||||
typedef RSAFunction PublicKey;
|
||||
typedef InvertibleRSAFunction PrivateKey;
|
||||
};
|
||||
|
||||
//! <a href="http://www.weidai.com/scan-mirror/ca.html#RSA">RSA cryptosystem</a>
|
||||
template <class STANDARD>
|
||||
struct RSAES : public TF_ES<STANDARD, RSA>
|
||||
{
|
||||
};
|
||||
|
||||
//! <a href="http://www.weidai.com/scan-mirror/sig.html#RSA">RSA signature scheme with appendix</a>
|
||||
/*! See documentation of PKCS1v15 for a list of hash functions that can be used with it. */
|
||||
template <class STANDARD, class H>
|
||||
struct RSASS : public TF_SS<STANDARD, H, RSA>
|
||||
{
|
||||
};
|
||||
|
||||
// The two RSA encryption schemes defined in PKCS #1 v2.0
|
||||
typedef RSAES<PKCS1v15>::Decryptor RSAES_PKCS1v15_Decryptor;
|
||||
typedef RSAES<PKCS1v15>::Encryptor RSAES_PKCS1v15_Encryptor;
|
||||
|
||||
typedef RSAES<OAEP<SHA> >::Decryptor RSAES_OAEP_SHA_Decryptor;
|
||||
typedef RSAES<OAEP<SHA> >::Encryptor RSAES_OAEP_SHA_Encryptor;
|
||||
|
||||
// The three RSA signature schemes defined in PKCS #1 v2.0
|
||||
typedef RSASS<PKCS1v15, SHA>::Signer RSASSA_PKCS1v15_SHA_Signer;
|
||||
typedef RSASS<PKCS1v15, SHA>::Verifier RSASSA_PKCS1v15_SHA_Verifier;
|
||||
|
||||
typedef RSASS<PKCS1v15, MD2>::Signer RSASSA_PKCS1v15_MD2_Signer;
|
||||
typedef RSASS<PKCS1v15, MD2>::Verifier RSASSA_PKCS1v15_MD2_Verifier;
|
||||
|
||||
typedef RSASS<PKCS1v15, MD5>::Signer RSASSA_PKCS1v15_MD5_Signer;
|
||||
typedef RSASS<PKCS1v15, MD5>::Verifier RSASSA_PKCS1v15_MD5_Verifier;
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,32 @@
|
||||
30820274020100300D06092A864886F70D010101
|
||||
05000482025E3082025A02010002818100A39D4F
|
||||
72D1BCFF65A47545C2897C0464CE9181E8703421
|
||||
2EC04407C4C24D569AA20C58B8138C85E17510BC
|
||||
6B861CADA9034C3ECE3B050B546E97D2BDC07A07
|
||||
CF8A612F7D3646739633041893EF18C411264E45
|
||||
C9E033A1BD5EE5FA02D95E9A9ADA2D0C6DF480E3
|
||||
2FA3FCE02889798455CE53F084AAB4C5549266F7
|
||||
CE8C77DF1D0201110281800E6FC33ED64561D443
|
||||
378627C0D63C9F7BA36D584622B7A23E241ECD98
|
||||
AC78952C6A804C7A320BD020EAE372E62FB4F853
|
||||
1D50D5F6261796823A929845B06A19B35A5227CB
|
||||
C819852A9CBE588CC2D1CEE07F426D13C2BF2FCA
|
||||
1C99FDEEFDFE387859E2B3F654E85A71481A71E9
|
||||
D5256583B1200F29C1AA0F437CFDC2AEAF218102
|
||||
4100D5DDB104AD074F6C1B8192D9AC8AED4DE05C
|
||||
F5C6509490DA8CCFC91FDF7B3A1323E03894DCAA
|
||||
B2587716D652A56904F86244E10C1B8FA597C389
|
||||
2591C55DBD65024100C3D930B583B8AD9A349218
|
||||
795C988CF0004F09DA04FFEF6FDF7CB4FA654F74
|
||||
B262521FE185693CD6290A337589F62CDEECE24E
|
||||
CCB5E79865275540F3B603FB59024064A48F89BA
|
||||
D6437E2B0FCCA2AB8CABE86995285D5318BCA315
|
||||
167CC3B47639726B3C56DCA41417B128FBB026E4
|
||||
6DA7FC6A7AC441EEDA2FCEF29AE480D5594A1102
|
||||
40228FBD4D355CD35772B05EAC014818DF0F1D01
|
||||
BD0FF0EE04AEF7E3B3B7867E015CA514AF53C746
|
||||
F89DD49FAB5494DABDED9159332F28DEA8705A56
|
||||
C198974A79024100D1DCA40FBD19036F0E2A9438
|
||||
7D03C090DDF0A677CDE0B8634A81F247752A355E
|
||||
C1CEA2482A4887767145C2BA703C9C10228FDA1E
|
||||
BB2EBEA73D23AA9C34182179
|
||||
@@ -0,0 +1,61 @@
|
||||
308204BB020100300D06092A864886F70D010101
|
||||
0500048204A5308204A10201000282010100BB25
|
||||
80EB6B368287A0A3BDDF6AAA9EDA2EEF15D92C5F
|
||||
E0B1C21473175C39B685A6FB0B0DB611092C19B4
|
||||
FA3CA5BB20F311E35B2E1097F48B077DF7684BEB
|
||||
9A34EB78C7B5F02ADFAEA3F3A66F1EF91B0C47DE
|
||||
68F0501F80A7E9603F794E928949F152C049A011
|
||||
D7E58C72F9303781E4FE7129DD7B87B5448D440A
|
||||
62CE8E9C801F245039E2724A9C37CB17457950B7
|
||||
B3C4C9BE4D17A29EFC1EA1EF464FBD21DABE9F10
|
||||
ED0EB132405D68E4304008083BB675DA97CB6219
|
||||
147A1EB93D38A9C4023540F871272A85B45447B3
|
||||
6DE9A708E412CD31B1CB6470E4A37CBEA6000F36
|
||||
632DF86FD3C34466C63BD80F1350E4DD5081597F
|
||||
F34F94F07AE6430DCC0563B1F7CF020111028201
|
||||
00034D763A5DC03580E33616ED5ABABA855B2E62
|
||||
4495DD8D002009656B5473772C85F55F10CE81CE
|
||||
77BE31E04657410B1F6535B4CF1E6914E152F4AB
|
||||
84DA2FD409F81BBB3DF0A96A58EACC9501F60162
|
||||
5C1356BF97D139C78A7E18496708EA7DE7B47266
|
||||
C81363B3FF888085E7403A028901FF3BA04C2EDE
|
||||
930EC0EFAC4DCF8FD054C1119562A1C7CA455D79
|
||||
36CB95A16CE611ABC97918961DE6720CE171CC69
|
||||
A590E9A041EC1DAC6FDCF2E04946C100E03DEFCA
|
||||
29FF480C926CD48589EB832D4476CF38AB320754
|
||||
D97BE77FDB9E5F2DCA1A2ABBC33D0790FE8C22CF
|
||||
694BB8E0265733A5A17CC5D07DB54515DC80216A
|
||||
A23A43EB12783888FF424EDB26FAF7DCB9028181
|
||||
00EB4C87F67AEA3F2047BF9DF61947DF2BA7E1C1
|
||||
64A03A8E3ED5F3BC6CDEE99FC6251C6A28F9502F
|
||||
0A4B5A0CFA8038A12A2270AAE2C9342EDBA207CE
|
||||
0F170B6D07550670CFEAE730B9411E66CD2D485F
|
||||
3FC3E9C5348D32C768F68A53C756E66BE0FAC7E8
|
||||
FDC9FBE22644961782DA5DDC19D75B64D2E8B660
|
||||
052DDC95AD186633E902818100CB9C7830223B78
|
||||
FC28A6D2B77C50C3D389F32FC4DEF33341741205
|
||||
5102F8D852663DB44E1EA5E5E58A71D30D33C168
|
||||
E94855D79CC19CC7DFBAFBDFF7710490064A1375
|
||||
1CD75466219956B9D4C0AF0CC13E7D075F54E6AF
|
||||
8CD67FBE3F4AB90425B039410686A168421E2E24
|
||||
FF0319D9D3F1C685BB650BC7B5BD12090CBDC392
|
||||
F702818060E3470B238DA185C330C89282E15BE4
|
||||
CCA84092D89094ECB2736BB45BC99C2469A249D4
|
||||
A2E4C8134C34237634CC06206888BED5DA60C800
|
||||
158ABE4272E6964E502FD41960B98C888439B1DC
|
||||
039645567DD8BA9D2B14E8B2BFDE9AF7BA5EE120
|
||||
674341D1E9C211D385A736DB871796DD76CB47A2
|
||||
239663C5E5B52E9291937EC902818053D704500E
|
||||
187D1C8935A20F514E6EC08418D76F2EA060663E
|
||||
DA3E6CA6DEEFA97564B3A7B2444F9AC08938C933
|
||||
6DC1C9782358C8137CCAC5893A8965E33E1D2FC4
|
||||
262129FE4FEDD1997E10488B935F9ADD7EC6CCE6
|
||||
B957581C167B83791F01B52A71ED99467EB27593
|
||||
F4E20EA6EC86DECCF7643E1A8C614AD561C77DB7
|
||||
8CC40B02818100AF950A287679E6C55020400E8A
|
||||
AD0642DB1C11D9AD5AE85F1B6FD2829D869453C9
|
||||
F67C0210D0847A4BD47C57FAECD9BE540BD66989
|
||||
E6C43F62D725B3D841B4F1DB7C28A722337358C8
|
||||
D1CD55F5CA6E31FAD6F827756BA074944D345C8D
|
||||
2FCE759F4244B948D06F5AC863DEAAEF279B2F69
|
||||
955ADAD1F39DEA9DA028B94EF22F11
|
||||
@@ -0,0 +1,10 @@
|
||||
30 4c 30 0d 06 09 2a 86
|
||||
48 86 f7 0d 01 01 01 05
|
||||
00 03 3b 00 30 38 02 33
|
||||
00 a3 07 9a 90 df 0d fd
|
||||
72 ac 09 0c cc 2a 78 b8
|
||||
74 13 13 3e 40 75 9c 98
|
||||
fa f8 20 4f 35 8a 0b 26
|
||||
3c 67 70 e7 83 a9 3b 69
|
||||
71 b7 37 79 d2 71 7b e8
|
||||
34 77 cf 02 01 03
|
||||
@@ -0,0 +1,41 @@
|
||||
30 81 fb
|
||||
02 01 00
|
||||
02
|
||||
33 00 a3 07 9a 90 df 0d
|
||||
fd 72 ac 09 0c cc 2a 78
|
||||
b8 74 13 13 3e 40 75 9c
|
||||
98 fa f8 20 4f 35 8a 0b
|
||||
26 3c 67 70 e7 83 a9 3b
|
||||
69 71 b7 37 79 d2 71 7b
|
||||
e8 34 77 cf
|
||||
02 01 03
|
||||
02
|
||||
32 6c af bc 60 94 b3 fe
|
||||
4c 72 b0 b3 32 c6 fb 25
|
||||
a2 b7 62 29 80 4e 68 65
|
||||
fc a4 5a 74 df 0f 8f b8
|
||||
41 3b 52 c0 d0 e5 3d 9b
|
||||
59 0f f1 9b e7 9f 49 dd
|
||||
21 e5 eb
|
||||
02 1a 00 cf 20
|
||||
35 02 8b 9d 86 98 40 b4
|
||||
16 66 b4 2e 92 ea 0d a3
|
||||
b4 32 04 b5 cf ce 91
|
||||
02
|
||||
1a 00 c9 7f b1 f0 27 f4
|
||||
53 f6 34 12 33 ea aa d1
|
||||
d9 35 3f 6c 42 d0 88 66
|
||||
b1 d0 5f
|
||||
02 1a 00 8a 15
|
||||
78 ac 5d 13 af 10 2b 22
|
||||
b9 99 cd 74 61 f1 5e 6d
|
||||
22 cc 03 23 df df 0b
|
||||
02
|
||||
1a 00 86 55 21 4a c5 4d
|
||||
8d 4e cd 61 77 f1 c7 36
|
||||
90 ce 2a 48 2c 8b 05 99
|
||||
cb e0 3f
|
||||
02 1a 00 83 ef
|
||||
ef b8 a9 a4 0d 1d b6 ed
|
||||
98 ad 84 ed 13 35 dc c1
|
||||
08 f3 22 d0 57 cf 8d
|
||||
@@ -0,0 +1,35 @@
|
||||
30 82 01 50
|
||||
02 01 00
|
||||
30 0d
|
||||
06 09
|
||||
2a 86 48 86 f7 0d 01 01 01
|
||||
05 00
|
||||
04 82 01 3a
|
||||
30 82 01 36
|
||||
02 01 00
|
||||
02 40
|
||||
0a 66 79 1d c6 98 81 68 de 7a b7 74 19 bb 7f b0
|
||||
c0 01 c6 27 10 27 00 75 14 29 42 e1 9a 8d 8c 51
|
||||
d0 53 b3 e3 78 2a 1d e5 dc 5a f4 eb e9 94 68 17
|
||||
01 14 a1 df e6 7c dc 9a 9a f5 5d 65 56 20 bb ab
|
||||
02 03 01 00 01
|
||||
02 40
|
||||
01 23 c5 b6 1b a3 6e db 1d 36 79 90 41 99 a8 9e
|
||||
a8 0c 09 b9 12 2e 14 00 c0 9a dc f7 78 46 76 d0
|
||||
1d 23 35 6a 7d 44 d6 bd 8b d5 0e 94 bf c7 23 fa
|
||||
87 d8 86 2b 75 17 76 91 c1 1d 75 76 92 df 88 81
|
||||
02 20
|
||||
33 d4 84 45 c8 59 e5 23 40 de 70 4b cd da 06 5f
|
||||
bb 40 58 d7 40 bd 1d 67 d2 9e 9c 14 6c 11 cf 61
|
||||
02 20
|
||||
33 5e 84 08 86 6b 0f d3 8d c7 00 2d 3f 97 2c 67
|
||||
38 9a 65 d5 d8 30 65 66 d5 c4 f2 a5 aa 52 62 8b
|
||||
02 20
|
||||
04 5e c9 00 71 52 53 25 d3 d4 6d b7 96 95 e9 af
|
||||
ac c4 52 39 64 36 0e 02 b1 19 ba a3 66 31 62 41
|
||||
02 20
|
||||
15 eb 32 73 60 c7 b6 0d 12 e5 e2 d1 6b dc d9 79
|
||||
81 d1 7f ba 6b 70 db 13 b2 0b 43 6e 24 ea da 59
|
||||
02 20
|
||||
2c a6 36 6d 72 78 1d fa 24 d3 4a 9a 24 cb c2 ae
|
||||
92 7a 99 58 af 42 65 63 ff 63 fb 11 65 8a 46 1d
|
||||
@@ -0,0 +1,385 @@
|
||||
// secblock.h - written and placed in the public domain by Wei Dai
|
||||
|
||||
#ifndef CRYPTOPP_SECBLOCK_H
|
||||
#define CRYPTOPP_SECBLOCK_H
|
||||
|
||||
#include "config.h"
|
||||
#include "misc.h"
|
||||
#include <string.h> // CodeWarrior doesn't have memory.h
|
||||
#include <assert.h>
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
// ************** secure memory allocation ***************
|
||||
|
||||
template<class T>
|
||||
class AllocatorBase
|
||||
{
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef size_t size_type;
|
||||
#if (defined(_MSC_VER) && _MSC_VER < 1300)
|
||||
typedef ptrdiff_t difference_type;
|
||||
#else
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
#endif
|
||||
typedef T * pointer;
|
||||
typedef const T * const_pointer;
|
||||
typedef T & reference;
|
||||
typedef const T & const_reference;
|
||||
|
||||
pointer address(reference r) const {return (&r);}
|
||||
const_pointer address(const_reference r) const {return (&r); }
|
||||
void construct(pointer p, const T& val) {new (p) T(val);}
|
||||
void destroy(pointer p) {p->~T();}
|
||||
size_type max_size() const {return size_type(-1)/sizeof(T);}
|
||||
};
|
||||
|
||||
#define CRYPTOPP_INHERIT_ALLOCATOR_TYPES \
|
||||
typedef typename AllocatorBase<T>::value_type value_type;\
|
||||
typedef typename AllocatorBase<T>::size_type size_type;\
|
||||
typedef typename AllocatorBase<T>::difference_type difference_type;\
|
||||
typedef typename AllocatorBase<T>::pointer pointer;\
|
||||
typedef typename AllocatorBase<T>::const_pointer const_pointer;\
|
||||
typedef typename AllocatorBase<T>::reference reference;\
|
||||
typedef typename AllocatorBase<T>::const_reference const_reference;
|
||||
|
||||
template <class T, class A>
|
||||
typename A::pointer StandardReallocate(A& a, T *p, typename A::size_type oldSize, typename A::size_type newSize, bool preserve)
|
||||
{
|
||||
if (oldSize == newSize)
|
||||
return p;
|
||||
|
||||
if (preserve)
|
||||
{
|
||||
typename A::pointer newPointer = a.allocate(newSize, NULL);
|
||||
memcpy(newPointer, p, sizeof(T)*STDMIN(oldSize, newSize));
|
||||
a.deallocate(p, oldSize);
|
||||
return newPointer;
|
||||
}
|
||||
else
|
||||
{
|
||||
a.deallocate(p, oldSize);
|
||||
return a.allocate(newSize, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
class AllocatorWithCleanup : public AllocatorBase<T>
|
||||
{
|
||||
public:
|
||||
CRYPTOPP_INHERIT_ALLOCATOR_TYPES
|
||||
|
||||
pointer allocate(size_type n, const void * = NULL)
|
||||
{
|
||||
if (n > 0)
|
||||
return new T[n];
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void deallocate(void *p, size_type n)
|
||||
{
|
||||
memset(p, 0, n*sizeof(T));
|
||||
delete [] (T *)p;
|
||||
}
|
||||
|
||||
pointer reallocate(T *p, size_type oldSize, size_type newSize, bool preserve)
|
||||
{
|
||||
return StandardReallocate(*this, p, oldSize, newSize, preserve);
|
||||
}
|
||||
|
||||
// VS.NET STL enforces the policy of "All STL-compliant allocators have to provide a
|
||||
// template class member called rebind".
|
||||
template <class U> struct rebind { typedef AllocatorWithCleanup<U> other; };
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class NullAllocator : public AllocatorBase<T>
|
||||
{
|
||||
public:
|
||||
CRYPTOPP_INHERIT_ALLOCATOR_TYPES
|
||||
|
||||
pointer allocate(size_type n, const void * = NULL)
|
||||
{
|
||||
assert(false);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void deallocate(void *p, size_type n)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
};
|
||||
|
||||
// this allocator can't be used with standard collections
|
||||
template <class T, unsigned int S, class A = NullAllocator<T> >
|
||||
class FixedSizeAllocatorWithCleanup : public AllocatorBase<T>
|
||||
{
|
||||
public:
|
||||
CRYPTOPP_INHERIT_ALLOCATOR_TYPES
|
||||
|
||||
pointer allocate(size_type n)
|
||||
{
|
||||
if (n <= S)
|
||||
{
|
||||
assert(!m_allocated);
|
||||
#ifndef NDEBUG
|
||||
m_allocated = true;
|
||||
#endif
|
||||
return m_array;
|
||||
}
|
||||
else
|
||||
return m_fallbackAllocator.allocate(n);
|
||||
}
|
||||
|
||||
pointer allocate(size_type n, const void *hint)
|
||||
{
|
||||
if (n <= S)
|
||||
{
|
||||
assert(!m_allocated);
|
||||
#ifndef NDEBUG
|
||||
m_allocated = true;
|
||||
#endif
|
||||
return m_array;
|
||||
}
|
||||
else
|
||||
return m_fallbackAllocator.allocate(n, hint);
|
||||
}
|
||||
|
||||
void deallocate(void *p, size_type n)
|
||||
{
|
||||
if (n <= S)
|
||||
{
|
||||
assert(m_allocated);
|
||||
assert(p == m_array);
|
||||
#ifndef NDEBUG
|
||||
m_allocated = false;
|
||||
#endif
|
||||
memset(p, 0, n*sizeof(T));
|
||||
}
|
||||
else
|
||||
m_fallbackAllocator.deallocate(p, n);
|
||||
}
|
||||
|
||||
pointer reallocate(pointer p, size_type oldSize, size_type newSize, bool preserve)
|
||||
{
|
||||
if (oldSize <= S && newSize <= S)
|
||||
return p;
|
||||
|
||||
return StandardReallocate(*this, p, oldSize, newSize, preserve);
|
||||
}
|
||||
|
||||
size_type max_size() const {return m_fallbackAllocator.max_size();}
|
||||
|
||||
private:
|
||||
A m_fallbackAllocator;
|
||||
T m_array[S];
|
||||
|
||||
#ifndef NDEBUG
|
||||
public:
|
||||
FixedSizeAllocatorWithCleanup() : m_allocated(false) {}
|
||||
bool m_allocated;
|
||||
#endif
|
||||
};
|
||||
|
||||
//! a block of memory allocated using A
|
||||
template <class T, class A = AllocatorWithCleanup<T> >
|
||||
class SecBlock
|
||||
{
|
||||
public:
|
||||
explicit SecBlock(unsigned int size=0)
|
||||
: m_size(size) {m_ptr = m_alloc.allocate(size, NULL);}
|
||||
SecBlock(const SecBlock<T, A> &t)
|
||||
: m_size(t.m_size) {m_ptr = m_alloc.allocate(m_size, NULL); memcpy(m_ptr, t.m_ptr, m_size*sizeof(T));}
|
||||
SecBlock(const T *t, unsigned int len)
|
||||
: m_size(len)
|
||||
{
|
||||
m_ptr = m_alloc.allocate(len, NULL);
|
||||
if (t == NULL)
|
||||
memset(m_ptr, 0, len*sizeof(T));
|
||||
else
|
||||
memcpy(m_ptr, t, len*sizeof(T));
|
||||
}
|
||||
|
||||
~SecBlock()
|
||||
{m_alloc.deallocate(m_ptr, m_size);}
|
||||
|
||||
#if defined(__GNUC__) || defined(__BCPLUSPLUS__)
|
||||
operator const void *() const
|
||||
{return m_ptr;}
|
||||
operator void *()
|
||||
{return m_ptr;}
|
||||
#endif
|
||||
#if defined(__GNUC__) // reduce warnings
|
||||
operator const void *()
|
||||
{return m_ptr;}
|
||||
#endif
|
||||
|
||||
operator const T *() const
|
||||
{return m_ptr;}
|
||||
operator T *()
|
||||
{return m_ptr;}
|
||||
#if defined(__GNUC__) // reduce warnings
|
||||
operator const T *()
|
||||
{return m_ptr;}
|
||||
#endif
|
||||
|
||||
template <typename I>
|
||||
T *operator +(I offset)
|
||||
{return m_ptr+offset;}
|
||||
|
||||
template <typename I>
|
||||
const T *operator +(I offset) const
|
||||
{return m_ptr+offset;}
|
||||
|
||||
template <typename I>
|
||||
T& operator[](I index)
|
||||
{assert(index >= 0 && (unsigned int)index < m_size); return m_ptr[index];}
|
||||
|
||||
template <typename I>
|
||||
const T& operator[](I index) const
|
||||
{assert(index >= 0 && (unsigned int)index < m_size); return m_ptr[index];}
|
||||
|
||||
typedef typename A::pointer iterator;
|
||||
typedef typename A::const_pointer const_iterator;
|
||||
typedef typename A::size_type size_type;
|
||||
|
||||
iterator begin()
|
||||
{return m_ptr;}
|
||||
const_iterator begin() const
|
||||
{return m_ptr;}
|
||||
iterator end()
|
||||
{return m_ptr+m_size;}
|
||||
const_iterator end() const
|
||||
{return m_ptr+m_size;}
|
||||
|
||||
typename A::pointer data() {return m_ptr;}
|
||||
typename A::const_pointer data() const {return m_ptr;}
|
||||
|
||||
size_type size() const {return m_size;}
|
||||
bool empty() const {return m_size == 0;}
|
||||
|
||||
void Assign(const T *t, unsigned int len)
|
||||
{
|
||||
New(len);
|
||||
memcpy(m_ptr, t, len*sizeof(T));
|
||||
}
|
||||
|
||||
void Assign(const SecBlock<T, A> &t)
|
||||
{
|
||||
New(t.m_size);
|
||||
memcpy(m_ptr, t.m_ptr, m_size*sizeof(T));
|
||||
}
|
||||
|
||||
SecBlock& operator=(const SecBlock<T, A> &t)
|
||||
{
|
||||
Assign(t);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const SecBlock<T, A> &t) const
|
||||
{
|
||||
return m_size == t.m_size && memcmp(m_ptr, t.m_ptr, m_size*sizeof(T)) == 0;
|
||||
}
|
||||
|
||||
bool operator!=(const SecBlock<T, A> &t) const
|
||||
{
|
||||
return !operator==(t);
|
||||
}
|
||||
|
||||
void New(unsigned int newSize)
|
||||
{
|
||||
m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, false);
|
||||
m_size = newSize;
|
||||
}
|
||||
|
||||
void CleanNew(unsigned int newSize)
|
||||
{
|
||||
New(newSize);
|
||||
memset(m_ptr, 0, m_size*sizeof(T));
|
||||
}
|
||||
|
||||
void Grow(unsigned int newSize)
|
||||
{
|
||||
if (newSize > m_size)
|
||||
{
|
||||
m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
|
||||
m_size = newSize;
|
||||
}
|
||||
}
|
||||
|
||||
void CleanGrow(unsigned int newSize)
|
||||
{
|
||||
if (newSize > m_size)
|
||||
{
|
||||
m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
|
||||
memset(m_ptr+m_size, 0, (newSize-m_size)*sizeof(T));
|
||||
m_size = newSize;
|
||||
}
|
||||
}
|
||||
|
||||
void resize(unsigned int newSize)
|
||||
{
|
||||
m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
|
||||
m_size = newSize;
|
||||
}
|
||||
|
||||
void swap(SecBlock<T, A> &b);
|
||||
|
||||
//private:
|
||||
A m_alloc;
|
||||
unsigned int m_size;
|
||||
T *m_ptr;
|
||||
};
|
||||
|
||||
template <class T, class A> void SecBlock<T, A>::swap(SecBlock<T, A> &b)
|
||||
{
|
||||
std::swap(m_alloc, b.m_alloc);
|
||||
std::swap(m_size, b.m_size);
|
||||
std::swap(m_ptr, b.m_ptr);
|
||||
}
|
||||
|
||||
typedef SecBlock<byte> SecByteBlock;
|
||||
typedef SecBlock<word> SecWordBlock;
|
||||
|
||||
template <class T, unsigned int S, class A = FixedSizeAllocatorWithCleanup<T, S> >
|
||||
class FixedSizeSecBlock : public SecBlock<T, A>
|
||||
{
|
||||
public:
|
||||
explicit FixedSizeSecBlock() : SecBlock<T, A>(S) {}
|
||||
};
|
||||
|
||||
template <class T, unsigned int S, class A = FixedSizeAllocatorWithCleanup<T, S, AllocatorWithCleanup<T> > >
|
||||
class SecBlockWithHint : public SecBlock<T, A>
|
||||
{
|
||||
public:
|
||||
explicit SecBlockWithHint(unsigned int size) : SecBlock<T, A>(size) {}
|
||||
};
|
||||
|
||||
template<class T, class U>
|
||||
inline bool operator==(const CryptoPP::AllocatorWithCleanup<T>&, const CryptoPP::AllocatorWithCleanup<U>&) {return (true);}
|
||||
template<class T, class U>
|
||||
inline bool operator!=(const CryptoPP::AllocatorWithCleanup<T>&, const CryptoPP::AllocatorWithCleanup<U>&) {return (false);}
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
NAMESPACE_BEGIN(std)
|
||||
template <class T, class A>
|
||||
inline void swap(CryptoPP::SecBlock<T, A> &a, CryptoPP::SecBlock<T, A> &b)
|
||||
{
|
||||
a.swap(b);
|
||||
}
|
||||
|
||||
#if defined(_STLPORT_VERSION) && !defined(_STLP_MEMBER_TEMPLATE_CLASSES)
|
||||
template <class _Tp1, class _Tp2>
|
||||
inline CryptoPP::AllocatorWithCleanup<_Tp2>&
|
||||
__stl_alloc_rebind(CryptoPP::AllocatorWithCleanup<_Tp1>& __a, const _Tp2*)
|
||||
{
|
||||
return (CryptoPP::AllocatorWithCleanup<_Tp2>&)(__a);
|
||||
}
|
||||
#endif
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,237 @@
|
||||
// seckey.h - written and placed in the public domain by Wei Dai
|
||||
|
||||
// This file contains helper classes/functions for implementing secret key algorithms.
|
||||
|
||||
#ifndef CRYPTOPP_SECKEY_H
|
||||
#define CRYPTOPP_SECKEY_H
|
||||
|
||||
#include "cryptlib.h"
|
||||
#include "misc.h"
|
||||
#include "simple.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
inline CipherDir ReverseCipherDir(CipherDir dir)
|
||||
{
|
||||
return (dir == ENCRYPTION) ? DECRYPTION : ENCRYPTION;
|
||||
}
|
||||
|
||||
//! .
|
||||
template <unsigned int N>
|
||||
class FixedBlockSize
|
||||
{
|
||||
public:
|
||||
enum {BLOCKSIZE = N};
|
||||
};
|
||||
|
||||
// ************** rounds ***************
|
||||
|
||||
//! .
|
||||
template <unsigned int R>
|
||||
class FixedRounds
|
||||
{
|
||||
public:
|
||||
enum {ROUNDS = R};
|
||||
|
||||
protected:
|
||||
template <class T>
|
||||
static inline void CheckedSetKey(T *obj, CipherDir dir, const byte *key, unsigned int length, const NameValuePairs ¶m)
|
||||
{
|
||||
obj->ThrowIfInvalidKeyLength(length);
|
||||
int rounds = param.GetIntValueWithDefault("Rounds", ROUNDS);
|
||||
if (rounds != ROUNDS)
|
||||
throw InvalidRounds(obj->StaticAlgorithmName(), rounds);
|
||||
obj->UncheckedSetKey(dir, key, length);
|
||||
}
|
||||
};
|
||||
|
||||
//! .
|
||||
template <unsigned int D, unsigned int N=1, unsigned int M=INT_MAX> // use INT_MAX here because enums are treated as signed ints
|
||||
class VariableRounds
|
||||
{
|
||||
public:
|
||||
enum {DEFAULT_ROUNDS = D, MIN_ROUNDS = N, MAX_ROUNDS = M};
|
||||
static unsigned int StaticGetDefaultRounds(unsigned int keylength) {return DEFAULT_ROUNDS;}
|
||||
|
||||
protected:
|
||||
static inline void AssertValidRounds(unsigned int rounds)
|
||||
{
|
||||
assert(rounds >= MIN_ROUNDS && rounds <= MAX_ROUNDS);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static inline void CheckedSetKey(T *obj, CipherDir dir, const byte *key, unsigned int length, const NameValuePairs ¶m)
|
||||
{
|
||||
obj->ThrowIfInvalidKeyLength(length);
|
||||
int rounds = param.GetIntValueWithDefault("Rounds", obj->StaticGetDefaultRounds(length));
|
||||
if (rounds < (unsigned int)MIN_ROUNDS || rounds > (unsigned int)MAX_ROUNDS)
|
||||
throw InvalidRounds(obj->AlgorithmName(), rounds);
|
||||
obj->UncheckedSetKey(dir, key, length, rounds);
|
||||
}
|
||||
};
|
||||
|
||||
// ************** key length ***************
|
||||
|
||||
//! .
|
||||
template <unsigned int N, unsigned int IV_REQ = SimpleKeyingInterface::NOT_RESYNCHRONIZABLE>
|
||||
class FixedKeyLength
|
||||
{
|
||||
public:
|
||||
enum {KEYLENGTH=N, MIN_KEYLENGTH=N, MAX_KEYLENGTH=N, DEFAULT_KEYLENGTH=N};
|
||||
enum {IV_REQUIREMENT = IV_REQ};
|
||||
static unsigned int StaticGetValidKeyLength(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, unsigned int IV_REQ = SimpleKeyingInterface::NOT_RESYNCHRONIZABLE>
|
||||
class VariableKeyLength
|
||||
{
|
||||
// make these private to avoid Doxygen documenting them in all derived classes
|
||||
CRYPTOPP_COMPILE_ASSERT(Q > 0);
|
||||
CRYPTOPP_COMPILE_ASSERT(N % Q == 0);
|
||||
CRYPTOPP_COMPILE_ASSERT(M % Q == 0);
|
||||
CRYPTOPP_COMPILE_ASSERT(N < M);
|
||||
CRYPTOPP_COMPILE_ASSERT(D >= N && M >= D);
|
||||
|
||||
public:
|
||||
enum {MIN_KEYLENGTH=N, MAX_KEYLENGTH=M, DEFAULT_KEYLENGTH=D, KEYLENGTH_MULTIPLE=Q};
|
||||
enum {IV_REQUIREMENT = IV_REQ};
|
||||
static unsigned int StaticGetValidKeyLength(unsigned int n)
|
||||
{
|
||||
if (n < (unsigned int)MIN_KEYLENGTH)
|
||||
return MIN_KEYLENGTH;
|
||||
else if (n > (unsigned int)MAX_KEYLENGTH)
|
||||
return (unsigned int)MAX_KEYLENGTH;
|
||||
else
|
||||
{
|
||||
n += KEYLENGTH_MULTIPLE-1;
|
||||
return n - 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};
|
||||
enum {IV_REQUIREMENT = T::IV_REQUIREMENT};
|
||||
static unsigned int StaticGetValidKeyLength(unsigned int keylength)
|
||||
{return T::StaticGetValidKeyLength(keylength);}
|
||||
};
|
||||
|
||||
// ************** implementation helper for SimpledKeyed ***************
|
||||
|
||||
template <class T>
|
||||
static inline void CheckedSetKey(T *obj, Empty empty, const byte *key, unsigned int length, const NameValuePairs ¶m)
|
||||
{
|
||||
obj->ThrowIfInvalidKeyLength(length);
|
||||
obj->UncheckedSetKey(key, length);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static inline void CheckedSetKey(T *obj, CipherDir dir, const byte *key, unsigned int length, const NameValuePairs ¶m)
|
||||
{
|
||||
obj->ThrowIfInvalidKeyLength(length);
|
||||
obj->UncheckedSetKey(dir, key, length);
|
||||
}
|
||||
|
||||
//! .
|
||||
template <class BASE, class INFO = BASE>
|
||||
class SimpleKeyingInterfaceImpl : public BASE
|
||||
{
|
||||
public:
|
||||
unsigned int MinKeyLength() const {return INFO::MIN_KEYLENGTH;}
|
||||
unsigned int MaxKeyLength() const {return (unsigned int)INFO::MAX_KEYLENGTH;}
|
||||
unsigned int DefaultKeyLength() const {return INFO::DEFAULT_KEYLENGTH;}
|
||||
unsigned int GetValidKeyLength(unsigned int n) const {return INFO::StaticGetValidKeyLength(n);}
|
||||
typename BASE::IV_Requirement IVRequirement() const {return (typename BASE::IV_Requirement)INFO::IV_REQUIREMENT;}
|
||||
|
||||
protected:
|
||||
void AssertValidKeyLength(unsigned int length) {assert(GetValidKeyLength(length) == length);}
|
||||
};
|
||||
|
||||
template <class INFO, class INTERFACE = BlockCipher>
|
||||
class BlockCipherBaseTemplate : public AlgorithmImpl<SimpleKeyingInterfaceImpl<TwoBases<INFO, INTERFACE> > >
|
||||
{
|
||||
public:
|
||||
unsigned int BlockSize() const {return BLOCKSIZE;}
|
||||
};
|
||||
|
||||
//! .
|
||||
template <CipherDir DIR, class BASE>
|
||||
class BlockCipherTemplate : public BASE
|
||||
{
|
||||
public:
|
||||
BlockCipherTemplate() {}
|
||||
BlockCipherTemplate(const byte *key)
|
||||
{SetKey(key, DEFAULT_KEYLENGTH);}
|
||||
BlockCipherTemplate(const byte *key, unsigned int length)
|
||||
{SetKey(key, length);}
|
||||
BlockCipherTemplate(const byte *key, unsigned int length, unsigned int rounds)
|
||||
{SetKeyWithRounds(key, length, rounds);}
|
||||
|
||||
bool IsForwardTransformation() const {return DIR == ENCRYPTION;}
|
||||
|
||||
void SetKey(const byte *key, unsigned int length, const NameValuePairs ¶m = g_nullNameValuePairs)
|
||||
{
|
||||
CheckedSetKey(this, DIR, key, length, param);
|
||||
}
|
||||
|
||||
Clonable * Clone() const {return new BlockCipherTemplate<DIR, BASE>(*this);}
|
||||
};
|
||||
|
||||
//! .
|
||||
template <class BASE>
|
||||
class MessageAuthenticationCodeTemplate : public
|
||||
#ifdef CRYPTOPP_DOXYGEN_PROCESSING
|
||||
MessageAuthenticationCode
|
||||
#else
|
||||
SimpleKeyingInterfaceImpl<BASE>
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
MessageAuthenticationCodeTemplate() {}
|
||||
MessageAuthenticationCodeTemplate(const byte *key)
|
||||
{SetKey(key, DEFAULT_KEYLENGTH);}
|
||||
MessageAuthenticationCodeTemplate(const byte *key, unsigned int length)
|
||||
{SetKey(key, length);}
|
||||
|
||||
std::string AlgorithmName() const {return StaticAlgorithmName();}
|
||||
|
||||
void SetKey(const byte *key, unsigned int length, const NameValuePairs ¶m = g_nullNameValuePairs)
|
||||
{
|
||||
CheckedSetKey(this, Empty(), key, length, param);
|
||||
}
|
||||
|
||||
Clonable * Clone() const {return new MessageAuthenticationCodeTemplate<BASE>(*this);}
|
||||
};
|
||||
|
||||
// ************** documentation ***************
|
||||
|
||||
//! These objects usually should not be used directly. See CipherModeDocumentation instead.
|
||||
/*! Each class derived from this one defines two types, Encryption and Decryption,
|
||||
both of which implement the BlockCipher interface. */
|
||||
struct BlockCipherDocumentation
|
||||
{
|
||||
//! implements the BlockCipher interface
|
||||
typedef BlockCipher Encryption;
|
||||
//! implements the BlockCipher interface
|
||||
typedef BlockCipher Decryption;
|
||||
};
|
||||
|
||||
/*! \brief Each class derived from this one defines two types, Encryption and Decryption,
|
||||
both of which implement the SymmetricCipher interface. See CipherModeDocumentation
|
||||
for information about using block ciphers. */
|
||||
struct SymmetricCipherDocumentation
|
||||
{
|
||||
//! implements the SymmetricCipher interface
|
||||
typedef SymmetricCipher Encryption;
|
||||
//! implements the SymmetricCipher interface
|
||||
typedef SymmetricCipher Decryption;
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,277 @@
|
||||
// sha.cpp - modified by Wei Dai from Steve Reid's public domain sha1.c
|
||||
|
||||
// Steve Reid implemented SHA-1. Wei Dai implemented SHA-2.
|
||||
// Both are in the public domain.
|
||||
|
||||
#include "pch.h"
|
||||
#include "sha.h"
|
||||
#include "misc.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
void SHA::Init()
|
||||
{
|
||||
m_digest[0] = 0x67452301L;
|
||||
m_digest[1] = 0xEFCDAB89L;
|
||||
m_digest[2] = 0x98BADCFEL;
|
||||
m_digest[3] = 0x10325476L;
|
||||
m_digest[4] = 0xC3D2E1F0L;
|
||||
}
|
||||
|
||||
// start of Steve Reid's code
|
||||
|
||||
#define blk0(i) (W[i] = data[i])
|
||||
#define blk1(i) (W[i&15] = rotlFixed(W[(i+13)&15]^W[(i+8)&15]^W[(i+2)&15]^W[i&15],1))
|
||||
|
||||
#define f1(x,y,z) (z^(x&(y^z)))
|
||||
#define f2(x,y,z) (x^y^z)
|
||||
#define f3(x,y,z) ((x&y)|(z&(x|y)))
|
||||
#define f4(x,y,z) (x^y^z)
|
||||
|
||||
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
|
||||
#define R0(v,w,x,y,z,i) z+=f1(w,x,y)+blk0(i)+0x5A827999+rotlFixed(v,5);w=rotlFixed(w,30);
|
||||
#define R1(v,w,x,y,z,i) z+=f1(w,x,y)+blk1(i)+0x5A827999+rotlFixed(v,5);w=rotlFixed(w,30);
|
||||
#define R2(v,w,x,y,z,i) z+=f2(w,x,y)+blk1(i)+0x6ED9EBA1+rotlFixed(v,5);w=rotlFixed(w,30);
|
||||
#define R3(v,w,x,y,z,i) z+=f3(w,x,y)+blk1(i)+0x8F1BBCDC+rotlFixed(v,5);w=rotlFixed(w,30);
|
||||
#define R4(v,w,x,y,z,i) z+=f4(w,x,y)+blk1(i)+0xCA62C1D6+rotlFixed(v,5);w=rotlFixed(w,30);
|
||||
|
||||
void SHA::Transform(word32 *state, const word32 *data)
|
||||
{
|
||||
word32 W[16];
|
||||
/* Copy context->state[] to working vars */
|
||||
word32 a = state[0];
|
||||
word32 b = state[1];
|
||||
word32 c = state[2];
|
||||
word32 d = state[3];
|
||||
word32 e = state[4];
|
||||
/* 4 rounds of 20 operations each. Loop unrolled. */
|
||||
R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
|
||||
R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
|
||||
R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
|
||||
R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
|
||||
R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
|
||||
R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
|
||||
R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
|
||||
R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
|
||||
R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
|
||||
R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
|
||||
R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
|
||||
R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
|
||||
R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
|
||||
R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
|
||||
R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
|
||||
R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
|
||||
R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
|
||||
R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
|
||||
R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
|
||||
R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
|
||||
/* Add the working vars back into context.state[] */
|
||||
state[0] += a;
|
||||
state[1] += b;
|
||||
state[2] += c;
|
||||
state[3] += d;
|
||||
state[4] += e;
|
||||
/* Wipe variables */
|
||||
a = b = c = d = e = 0;
|
||||
memset(W, 0, sizeof(W));
|
||||
}
|
||||
|
||||
// end of Steve Reid's code
|
||||
|
||||
// *************************************************************
|
||||
|
||||
void SHA256::Init()
|
||||
{
|
||||
m_digest[0] = 0x6a09e667;
|
||||
m_digest[1] = 0xbb67ae85;
|
||||
m_digest[2] = 0x3c6ef372;
|
||||
m_digest[3] = 0xa54ff53a;
|
||||
m_digest[4] = 0x510e527f;
|
||||
m_digest[5] = 0x9b05688c;
|
||||
m_digest[6] = 0x1f83d9ab;
|
||||
m_digest[7] = 0x5be0cd19;
|
||||
}
|
||||
|
||||
#define blk2(i) (W[i&15]+=s1(W[(i-2)&15])+W[(i-7)&15]+s0(W[(i-15)&15]))
|
||||
|
||||
#define Ch(x,y,z) (z^(x&(y^z)))
|
||||
#define Maj(x,y,z) ((x&y)|(z&(x|y)))
|
||||
|
||||
#define a(i) T[(0-i)&7]
|
||||
#define b(i) T[(1-i)&7]
|
||||
#define c(i) T[(2-i)&7]
|
||||
#define d(i) T[(3-i)&7]
|
||||
#define e(i) T[(4-i)&7]
|
||||
#define f(i) T[(5-i)&7]
|
||||
#define g(i) T[(6-i)&7]
|
||||
#define h(i) T[(7-i)&7]
|
||||
|
||||
#define R(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+K[i+j]+(j?blk2(i):blk0(i));\
|
||||
d(i)+=h(i);h(i)+=S0(a(i))+Maj(a(i),b(i),c(i))
|
||||
|
||||
// for SHA256
|
||||
#define S0(x) (rotrFixed(x,2)^rotrFixed(x,13)^rotrFixed(x,22))
|
||||
#define S1(x) (rotrFixed(x,6)^rotrFixed(x,11)^rotrFixed(x,25))
|
||||
#define s0(x) (rotrFixed(x,7)^rotrFixed(x,18)^(x>>3))
|
||||
#define s1(x) (rotrFixed(x,17)^rotrFixed(x,19)^(x>>10))
|
||||
|
||||
void SHA256::Transform(word32 *state, const word32 *data)
|
||||
{
|
||||
word32 W[16];
|
||||
word32 T[8];
|
||||
/* Copy context->state[] to working vars */
|
||||
memcpy(T, state, sizeof(T));
|
||||
/* 64 operations, partially loop unrolled */
|
||||
for (unsigned int j=0; j<64; j+=16)
|
||||
{
|
||||
R( 0); R( 1); R( 2); R( 3);
|
||||
R( 4); R( 5); R( 6); R( 7);
|
||||
R( 8); R( 9); R(10); R(11);
|
||||
R(12); R(13); R(14); R(15);
|
||||
}
|
||||
/* Add the working vars back into context.state[] */
|
||||
state[0] += a(0);
|
||||
state[1] += b(0);
|
||||
state[2] += c(0);
|
||||
state[3] += d(0);
|
||||
state[4] += e(0);
|
||||
state[5] += f(0);
|
||||
state[6] += g(0);
|
||||
state[7] += h(0);
|
||||
/* Wipe variables */
|
||||
memset(W, 0, sizeof(W));
|
||||
memset(T, 0, sizeof(T));
|
||||
}
|
||||
|
||||
const word32 SHA256::K[64] = {
|
||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
|
||||
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||||
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
||||
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
||||
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
|
||||
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
|
||||
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
||||
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
||||
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
||||
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
|
||||
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
|
||||
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
||||
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
||||
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
||||
};
|
||||
|
||||
#undef S0
|
||||
#undef S1
|
||||
#undef s0
|
||||
#undef s1
|
||||
|
||||
// *************************************************************
|
||||
|
||||
#ifdef WORD64_AVAILABLE
|
||||
|
||||
void SHA512::Init()
|
||||
{
|
||||
m_digest[0] = W64LIT(0x6a09e667f3bcc908);
|
||||
m_digest[1] = W64LIT(0xbb67ae8584caa73b);
|
||||
m_digest[2] = W64LIT(0x3c6ef372fe94f82b);
|
||||
m_digest[3] = W64LIT(0xa54ff53a5f1d36f1);
|
||||
m_digest[4] = W64LIT(0x510e527fade682d1);
|
||||
m_digest[5] = W64LIT(0x9b05688c2b3e6c1f);
|
||||
m_digest[6] = W64LIT(0x1f83d9abfb41bd6b);
|
||||
m_digest[7] = W64LIT(0x5be0cd19137e2179);
|
||||
}
|
||||
|
||||
// for SHA512
|
||||
#define S0(x) (rotrFixed(x,28)^rotrFixed(x,34)^rotrFixed(x,39))
|
||||
#define S1(x) (rotrFixed(x,14)^rotrFixed(x,18)^rotrFixed(x,41))
|
||||
#define s0(x) (rotrFixed(x,1)^rotrFixed(x,8)^(x>>7))
|
||||
#define s1(x) (rotrFixed(x,19)^rotrFixed(x,61)^(x>>6))
|
||||
|
||||
void SHA512::Transform(word64 *state, const word64 *data)
|
||||
{
|
||||
word64 W[16];
|
||||
word64 T[8];
|
||||
/* Copy context->state[] to working vars */
|
||||
memcpy(T, state, sizeof(T));
|
||||
/* 80 operations, partially loop unrolled */
|
||||
for (unsigned int j=0; j<80; j+=16)
|
||||
{
|
||||
R( 0); R( 1); R( 2); R( 3);
|
||||
R( 4); R( 5); R( 6); R( 7);
|
||||
R( 8); R( 9); R(10); R(11);
|
||||
R(12); R(13); R(14); R(15);
|
||||
}
|
||||
/* Add the working vars back into context.state[] */
|
||||
state[0] += a(0);
|
||||
state[1] += b(0);
|
||||
state[2] += c(0);
|
||||
state[3] += d(0);
|
||||
state[4] += e(0);
|
||||
state[5] += f(0);
|
||||
state[6] += g(0);
|
||||
state[7] += h(0);
|
||||
/* Wipe variables */
|
||||
memset(W, 0, sizeof(W));
|
||||
memset(T, 0, sizeof(T));
|
||||
}
|
||||
|
||||
const word64 SHA512::K[80] = {
|
||||
W64LIT(0x428a2f98d728ae22), W64LIT(0x7137449123ef65cd),
|
||||
W64LIT(0xb5c0fbcfec4d3b2f), W64LIT(0xe9b5dba58189dbbc),
|
||||
W64LIT(0x3956c25bf348b538), W64LIT(0x59f111f1b605d019),
|
||||
W64LIT(0x923f82a4af194f9b), W64LIT(0xab1c5ed5da6d8118),
|
||||
W64LIT(0xd807aa98a3030242), W64LIT(0x12835b0145706fbe),
|
||||
W64LIT(0x243185be4ee4b28c), W64LIT(0x550c7dc3d5ffb4e2),
|
||||
W64LIT(0x72be5d74f27b896f), W64LIT(0x80deb1fe3b1696b1),
|
||||
W64LIT(0x9bdc06a725c71235), W64LIT(0xc19bf174cf692694),
|
||||
W64LIT(0xe49b69c19ef14ad2), W64LIT(0xefbe4786384f25e3),
|
||||
W64LIT(0x0fc19dc68b8cd5b5), W64LIT(0x240ca1cc77ac9c65),
|
||||
W64LIT(0x2de92c6f592b0275), W64LIT(0x4a7484aa6ea6e483),
|
||||
W64LIT(0x5cb0a9dcbd41fbd4), W64LIT(0x76f988da831153b5),
|
||||
W64LIT(0x983e5152ee66dfab), W64LIT(0xa831c66d2db43210),
|
||||
W64LIT(0xb00327c898fb213f), W64LIT(0xbf597fc7beef0ee4),
|
||||
W64LIT(0xc6e00bf33da88fc2), W64LIT(0xd5a79147930aa725),
|
||||
W64LIT(0x06ca6351e003826f), W64LIT(0x142929670a0e6e70),
|
||||
W64LIT(0x27b70a8546d22ffc), W64LIT(0x2e1b21385c26c926),
|
||||
W64LIT(0x4d2c6dfc5ac42aed), W64LIT(0x53380d139d95b3df),
|
||||
W64LIT(0x650a73548baf63de), W64LIT(0x766a0abb3c77b2a8),
|
||||
W64LIT(0x81c2c92e47edaee6), W64LIT(0x92722c851482353b),
|
||||
W64LIT(0xa2bfe8a14cf10364), W64LIT(0xa81a664bbc423001),
|
||||
W64LIT(0xc24b8b70d0f89791), W64LIT(0xc76c51a30654be30),
|
||||
W64LIT(0xd192e819d6ef5218), W64LIT(0xd69906245565a910),
|
||||
W64LIT(0xf40e35855771202a), W64LIT(0x106aa07032bbd1b8),
|
||||
W64LIT(0x19a4c116b8d2d0c8), W64LIT(0x1e376c085141ab53),
|
||||
W64LIT(0x2748774cdf8eeb99), W64LIT(0x34b0bcb5e19b48a8),
|
||||
W64LIT(0x391c0cb3c5c95a63), W64LIT(0x4ed8aa4ae3418acb),
|
||||
W64LIT(0x5b9cca4f7763e373), W64LIT(0x682e6ff3d6b2b8a3),
|
||||
W64LIT(0x748f82ee5defb2fc), W64LIT(0x78a5636f43172f60),
|
||||
W64LIT(0x84c87814a1f0ab72), W64LIT(0x8cc702081a6439ec),
|
||||
W64LIT(0x90befffa23631e28), W64LIT(0xa4506cebde82bde9),
|
||||
W64LIT(0xbef9a3f7b2c67915), W64LIT(0xc67178f2e372532b),
|
||||
W64LIT(0xca273eceea26619c), W64LIT(0xd186b8c721c0c207),
|
||||
W64LIT(0xeada7dd6cde0eb1e), W64LIT(0xf57d4f7fee6ed178),
|
||||
W64LIT(0x06f067aa72176fba), W64LIT(0x0a637dc5a2c898a6),
|
||||
W64LIT(0x113f9804bef90dae), W64LIT(0x1b710b35131c471b),
|
||||
W64LIT(0x28db77f523047d84), W64LIT(0x32caab7b40c72493),
|
||||
W64LIT(0x3c9ebe0a15c9bebc), W64LIT(0x431d67c49c100d4c),
|
||||
W64LIT(0x4cc5d4becb3e42b6), W64LIT(0x597f299cfc657e2a),
|
||||
W64LIT(0x5fcb6fab3ad6faec), W64LIT(0x6c44198c4a475817)
|
||||
};
|
||||
|
||||
void SHA384::Init()
|
||||
{
|
||||
m_digest[0] = W64LIT(0xcbbb9d5dc1059ed8);
|
||||
m_digest[1] = W64LIT(0x629a292a367cd507);
|
||||
m_digest[2] = W64LIT(0x9159015a3070dd17);
|
||||
m_digest[3] = W64LIT(0x152fecd8f70e5939);
|
||||
m_digest[4] = W64LIT(0x67332667ffc00b31);
|
||||
m_digest[5] = W64LIT(0x8eb44a8768581511);
|
||||
m_digest[6] = W64LIT(0xdb0c2e0d64f98fa7);
|
||||
m_digest[7] = W64LIT(0x47b5481dbefa4fa4);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -0,0 +1,72 @@
|
||||
#ifndef CRYPTOPP_SHA_H
|
||||
#define CRYPTOPP_SHA_H
|
||||
|
||||
#include "iterhash.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
/// <a href="http://www.weidai.com/scan-mirror/md.html#SHA-1">SHA-1</a>
|
||||
class SHA : public IteratedHashWithStaticTransform<word32, BigEndian, 64, SHA>
|
||||
{
|
||||
public:
|
||||
enum {DIGESTSIZE = 20};
|
||||
SHA() : IteratedHashWithStaticTransform<word32, BigEndian, 64, SHA>(DIGESTSIZE) {Init();}
|
||||
static void Transform(word32 *digest, const word32 *data);
|
||||
static const char *StaticAlgorithmName() {return "SHA-1";}
|
||||
|
||||
protected:
|
||||
void Init();
|
||||
};
|
||||
|
||||
typedef SHA SHA1;
|
||||
|
||||
//! implements the SHA-256 standard
|
||||
class SHA256 : public IteratedHashWithStaticTransform<word32, BigEndian, 64, SHA256>
|
||||
{
|
||||
public:
|
||||
enum {DIGESTSIZE = 32};
|
||||
SHA256() : IteratedHashWithStaticTransform<word32, BigEndian, 64, SHA256>(DIGESTSIZE) {Init();}
|
||||
static void Transform(word32 *digest, const word32 *data);
|
||||
static const char *StaticAlgorithmName() {return "SHA-256";}
|
||||
|
||||
protected:
|
||||
void Init();
|
||||
|
||||
static const word32 K[64];
|
||||
};
|
||||
|
||||
#ifdef WORD64_AVAILABLE
|
||||
|
||||
//! implements the SHA-512 standard
|
||||
class SHA512 : public IteratedHashWithStaticTransform<word64, BigEndian, 128, SHA512>
|
||||
{
|
||||
public:
|
||||
enum {DIGESTSIZE = 64};
|
||||
SHA512() : IteratedHashWithStaticTransform<word64, BigEndian, 128, SHA512>(DIGESTSIZE) {Init();}
|
||||
static void Transform(word64 *digest, const word64 *data);
|
||||
static const char *StaticAlgorithmName() {return "SHA-512";}
|
||||
|
||||
protected:
|
||||
void Init();
|
||||
|
||||
static const word64 K[80];
|
||||
};
|
||||
|
||||
//! implements the SHA-384 standard
|
||||
class SHA384 : public IteratedHashWithStaticTransform<word64, BigEndian, 128, SHA512>
|
||||
{
|
||||
public:
|
||||
enum {DIGESTSIZE = 48};
|
||||
SHA384() : IteratedHashWithStaticTransform<word64, BigEndian, 128, SHA512>(64) {Init();}
|
||||
unsigned int DigestSize() const {return DIGESTSIZE;};
|
||||
static const char *StaticAlgorithmName() {return "SHA-384";}
|
||||
|
||||
protected:
|
||||
void Init();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,230 @@
|
||||
// simple.h - written and placed in the public domain by Wei Dai
|
||||
/*! \file
|
||||
Simple non-interface classes derived from classes in cryptlib.h.
|
||||
*/
|
||||
|
||||
#ifndef CRYPTOPP_SIMPLE_H
|
||||
#define CRYPTOPP_SIMPLE_H
|
||||
|
||||
#include "cryptlib.h"
|
||||
#include "misc.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
template <class BASE, class ALGORITHM_INFO = BASE>
|
||||
class AlgorithmImpl : public BASE
|
||||
{
|
||||
public:
|
||||
std::string AlgorithmName() const {return ALGORITHM_INFO::StaticAlgorithmName();}
|
||||
};
|
||||
|
||||
//! .
|
||||
class InvalidKeyLength : public InvalidArgument
|
||||
{
|
||||
public:
|
||||
explicit InvalidKeyLength(const std::string &algorithm, unsigned int length) : InvalidArgument(algorithm + ": " + IntToString(length) + " is not a valid key length") {}
|
||||
};
|
||||
|
||||
//! .
|
||||
class InvalidRounds : public InvalidArgument
|
||||
{
|
||||
public:
|
||||
explicit InvalidRounds(const std::string &algorithm, unsigned int rounds) : InvalidArgument(algorithm + ": " + IntToString(rounds) + " is not a valid number of rounds") {}
|
||||
};
|
||||
|
||||
class HashTransformationWithDefaultTruncation : public HashTransformation
|
||||
{
|
||||
public:
|
||||
virtual void Final(byte *digest) =0;
|
||||
void TruncatedFinal(byte *digest, unsigned int digestSize);
|
||||
};
|
||||
|
||||
//! .
|
||||
// TODO: look into this virtual inheritance
|
||||
class ASN1CryptoMaterial : virtual public ASN1Object, virtual public CryptoMaterial
|
||||
{
|
||||
public:
|
||||
void Save(BufferedTransformation &bt) const
|
||||
{BEREncode(bt);}
|
||||
void Load(BufferedTransformation &bt)
|
||||
{BERDecode(bt);}
|
||||
};
|
||||
|
||||
// *****************************
|
||||
|
||||
template <class T>
|
||||
class Bufferless : public T
|
||||
{
|
||||
public:
|
||||
Bufferless() {}
|
||||
Bufferless(BufferedTransformation *q) : T(q) {}
|
||||
bool IsolatedFlush(bool hardFlush, bool blocking) {return false;}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class Unflushable : public T
|
||||
{
|
||||
public:
|
||||
Unflushable() {}
|
||||
Unflushable(BufferedTransformation *q) : T(q) {}
|
||||
bool Flush(bool completeFlush, int propagation=-1, bool blocking=true)
|
||||
{return ChannelFlush(NULL_CHANNEL, completeFlush, propagation);}
|
||||
bool IsolatedFlush(bool hardFlush, bool blocking)
|
||||
{assert(false); return false;}
|
||||
bool ChannelFlush(const std::string &channel, bool hardFlush, int propagation=-1, bool blocking=true)
|
||||
{
|
||||
if (hardFlush && !InputBufferIsEmpty())
|
||||
throw CannotFlush("Unflushable<T>: this object has buffered input that cannot be flushed");
|
||||
else
|
||||
{
|
||||
BufferedTransformation *attached = AttachedTransformation();
|
||||
return attached && propagation ? attached->ChannelFlush(channel, hardFlush, propagation-1, blocking) : false;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool InputBufferIsEmpty() const {return false;}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class InputRejecting : public T
|
||||
{
|
||||
public:
|
||||
InputRejecting() {}
|
||||
InputRejecting(BufferedTransformation *q) : T(q) {}
|
||||
|
||||
protected:
|
||||
struct InputRejected : public NotImplemented
|
||||
{InputRejected() : NotImplemented("BufferedTransformation: this object doesn't allow input") {}};
|
||||
|
||||
// shouldn't be calling these functions on this class
|
||||
unsigned int Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking)
|
||||
{throw InputRejected();}
|
||||
bool IsolatedFlush(bool, bool) {return false;}
|
||||
bool IsolatedMessageSeriesEnd(bool) {throw InputRejected();}
|
||||
|
||||
unsigned int ChannelPut2(const std::string &channel, const byte *begin, unsigned int length, int messageEnd, bool blocking)
|
||||
{throw InputRejected();}
|
||||
bool ChannelMessageSeriesEnd(const std::string &, int, bool) {throw InputRejected();}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class CustomSignalPropagation : public T
|
||||
{
|
||||
public:
|
||||
CustomSignalPropagation() {}
|
||||
CustomSignalPropagation(BufferedTransformation *q) : T(q) {}
|
||||
|
||||
virtual void Initialize(const NameValuePairs ¶meters=g_nullNameValuePairs, int propagation=-1) =0;
|
||||
virtual bool Flush(bool hardFlush, int propagation=-1, bool blocking=true) =0;
|
||||
|
||||
private:
|
||||
void IsolatedInitialize(const NameValuePairs ¶meters) {assert(false);}
|
||||
bool IsolatedFlush(bool hardFlush, bool blocking) {assert(false); return false;}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class Multichannel : public CustomSignalPropagation<T>
|
||||
{
|
||||
public:
|
||||
Multichannel() {}
|
||||
Multichannel(BufferedTransformation *q) : CustomSignalPropagation<T>(q) {}
|
||||
|
||||
void Initialize(const NameValuePairs ¶meters, int propagation)
|
||||
{ChannelInitialize(NULL_CHANNEL, parameters, propagation);}
|
||||
bool Flush(bool hardFlush, int propagation=-1, bool blocking=true)
|
||||
{return ChannelFlush(NULL_CHANNEL, hardFlush, propagation, blocking);}
|
||||
bool MessageSeriesEnd(int propagation=-1, bool blocking=true)
|
||||
{return ChannelMessageSeriesEnd(NULL_CHANNEL, propagation, blocking);}
|
||||
byte * CreatePutSpace(unsigned int &size)
|
||||
{return ChannelCreatePutSpace(NULL_CHANNEL, size);}
|
||||
unsigned int Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking)
|
||||
{return ChannelPut2(NULL_CHANNEL, begin, length, messageEnd, blocking);}
|
||||
unsigned int PutModifiable2(byte *inString, unsigned int length, int messageEnd, bool blocking)
|
||||
{return ChannelPutModifiable2(NULL_CHANNEL, inString, length, messageEnd, blocking);}
|
||||
|
||||
// void ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1)
|
||||
// {PropagateMessageSeriesEnd(propagation, channel);}
|
||||
byte * ChannelCreatePutSpace(const std::string &channel, unsigned int &size)
|
||||
{size = 0; return NULL;}
|
||||
bool ChannelPutModifiable(const std::string &channel, byte *inString, unsigned int length)
|
||||
{ChannelPut(channel, inString, length); return false;}
|
||||
|
||||
virtual unsigned int ChannelPut2(const std::string &channel, const byte *begin, unsigned int length, int messageEnd, bool blocking) =0;
|
||||
unsigned int ChannelPutModifiable2(const std::string &channel, byte *begin, unsigned int length, int messageEnd, bool blocking)
|
||||
{return ChannelPut2(channel, begin, length, messageEnd, blocking);}
|
||||
|
||||
virtual void ChannelInitialize(const std::string &channel, const NameValuePairs ¶meters=g_nullNameValuePairs, int propagation=-1) =0;
|
||||
virtual bool ChannelFlush(const std::string &channel, bool hardFlush, int propagation=-1, bool blocking=true) =0;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class AutoSignaling : public T
|
||||
{
|
||||
public:
|
||||
AutoSignaling(int propagation=-1) : m_autoSignalPropagation(propagation) {}
|
||||
AutoSignaling(BufferedTransformation *q, int propagation=-1) : T(q), 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 data as "output"
|
||||
class Store : public AutoSignaling<InputRejecting<BufferedTransformation> >
|
||||
{
|
||||
public:
|
||||
Store() : m_messageEnd(false) {}
|
||||
|
||||
void IsolatedInitialize(const NameValuePairs ¶meters)
|
||||
{
|
||||
m_messageEnd = false;
|
||||
StoreInitialize(parameters);
|
||||
}
|
||||
|
||||
unsigned int NumberOfMessages() const {return m_messageEnd ? 0 : 1;}
|
||||
bool GetNextMessage();
|
||||
unsigned int CopyMessagesTo(BufferedTransformation &target, unsigned int count=UINT_MAX, const std::string &channel=NULL_CHANNEL) const;
|
||||
|
||||
protected:
|
||||
virtual void StoreInitialize(const NameValuePairs ¶meters) =0;
|
||||
|
||||
bool m_messageEnd;
|
||||
};
|
||||
|
||||
//! A BufferedTransformation that doesn't produce any retrievable output
|
||||
class Sink : public BufferedTransformation
|
||||
{
|
||||
protected:
|
||||
// make these functions protected to help prevent unintentional calls to them
|
||||
BufferedTransformation::Get;
|
||||
BufferedTransformation::Peek;
|
||||
BufferedTransformation::TransferTo;
|
||||
BufferedTransformation::CopyTo;
|
||||
BufferedTransformation::CopyRangeTo;
|
||||
BufferedTransformation::TransferMessagesTo;
|
||||
BufferedTransformation::CopyMessagesTo;
|
||||
BufferedTransformation::TransferAllTo;
|
||||
BufferedTransformation::CopyAllTo;
|
||||
unsigned int TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel=NULL_CHANNEL, bool blocking=true)
|
||||
{transferBytes = 0; return 0;}
|
||||
unsigned int CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end=ULONG_MAX, const std::string &channel=NULL_CHANNEL, bool blocking=true) const
|
||||
{return 0;}
|
||||
};
|
||||
|
||||
class BitBucket : public Bufferless<Sink>
|
||||
{
|
||||
public:
|
||||
std::string AlgorithmName() const {return "BitBucket";}
|
||||
void IsolatedInitialize(const NameValuePairs ¶meters) {}
|
||||
unsigned int Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking)
|
||||
{return 0;}
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,215 @@
|
||||
#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 (!m_p && !rhs.m_p) || (m_p && rhs.m_p && *m_p == *rhs.m_p);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T> value_ptr<T>& value_ptr<T>::operator=(const value_ptr<T>& rhs)
|
||||
{
|
||||
T *old_p = m_p;
|
||||
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 = m_p;
|
||||
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 T &r) : m_p(0) {attach(r);}
|
||||
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 get(); }
|
||||
|
||||
const T* get() const { return m_p; }
|
||||
T* get();
|
||||
|
||||
void attach(const T &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> void counted_ptr<T>::attach(const T &r)
|
||||
{
|
||||
if (m_p && --m_p->m_referenceCount == 0)
|
||||
delete m_p;
|
||||
if (r.m_referenceCount == 0)
|
||||
{
|
||||
m_p = r.clone();
|
||||
m_p->m_referenceCount = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_p = const_cast<T *>(&r);
|
||||
m_p->m_referenceCount++;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T> T* counted_ptr<T>::get()
|
||||
{
|
||||
if (m_p && m_p->m_referenceCount > 1)
|
||||
{
|
||||
T *temp = m_p->clone();
|
||||
m_p->m_referenceCount--;
|
||||
m_p = temp;
|
||||
m_p->m_referenceCount = 1;
|
||||
}
|
||||
return m_p;
|
||||
}
|
||||
|
||||
template <class T> counted_ptr<T> & counted_ptr<T>::operator=(const counted_ptr<T>& rhs)
|
||||
{
|
||||
if (m_p != rhs.m_p)
|
||||
{
|
||||
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;
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,188 @@
|
||||
// strciphr.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "pch.h"
|
||||
#include "strciphr.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
template <class S>
|
||||
byte AdditiveCipherTemplate<S>::GenerateByte()
|
||||
{
|
||||
PolicyInterface &policy = AccessPolicy();
|
||||
|
||||
if (m_leftOver == 0)
|
||||
{
|
||||
policy.WriteKeystream(m_buffer, policy.GetIterationsToBuffer());
|
||||
m_leftOver = policy.GetBytesPerIteration();
|
||||
}
|
||||
|
||||
return *(KeystreamBufferEnd()-m_leftOver--);
|
||||
}
|
||||
|
||||
template <class S>
|
||||
inline void AdditiveCipherTemplate<S>::ProcessData(byte *outString, const byte *inString, unsigned int length)
|
||||
{
|
||||
if (m_leftOver > 0)
|
||||
{
|
||||
unsigned int len = STDMIN(m_leftOver, length);
|
||||
xorbuf(outString, inString, KeystreamBufferEnd()-m_leftOver, len);
|
||||
length -= len;
|
||||
m_leftOver -= len;
|
||||
inString += len;
|
||||
outString += len;
|
||||
}
|
||||
|
||||
if (!length)
|
||||
return;
|
||||
|
||||
assert(m_leftOver == 0);
|
||||
|
||||
PolicyInterface &policy = AccessPolicy();
|
||||
unsigned int bytesPerIteration = policy.GetBytesPerIteration();
|
||||
unsigned int alignment = policy.GetAlignment();
|
||||
|
||||
if (policy.CanOperateKeystream() && length >= bytesPerIteration && IsAlignedOn(outString, alignment))
|
||||
{
|
||||
if (IsAlignedOn(inString, alignment))
|
||||
policy.OperateKeystream(XOR_KEYSTREAM, outString, inString, length / bytesPerIteration);
|
||||
else
|
||||
{
|
||||
memcpy(outString, inString, length);
|
||||
policy.OperateKeystream(XOR_KEYSTREAM_INPLACE, outString, outString, length / bytesPerIteration);
|
||||
}
|
||||
inString += length - length % bytesPerIteration;
|
||||
outString += length - length % bytesPerIteration;
|
||||
length %= bytesPerIteration;
|
||||
|
||||
if (!length)
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int bufferByteSize = GetBufferByteSize(policy);
|
||||
unsigned int bufferIterations = policy.GetIterationsToBuffer();
|
||||
|
||||
while (length >= bufferByteSize)
|
||||
{
|
||||
policy.WriteKeystream(m_buffer, bufferIterations);
|
||||
xorbuf(outString, inString, KeystreamBufferBegin(), bufferByteSize);
|
||||
length -= bufferByteSize;
|
||||
inString += bufferByteSize;
|
||||
outString += bufferByteSize;
|
||||
}
|
||||
|
||||
if (length > 0)
|
||||
{
|
||||
policy.WriteKeystream(m_buffer, bufferIterations);
|
||||
xorbuf(outString, inString, KeystreamBufferBegin(), length);
|
||||
m_leftOver = bytesPerIteration - length;
|
||||
}
|
||||
}
|
||||
|
||||
template <class S>
|
||||
void AdditiveCipherTemplate<S>::Resynchronize(const byte *iv)
|
||||
{
|
||||
PolicyInterface &policy = AccessPolicy();
|
||||
m_leftOver = 0;
|
||||
m_buffer.New(GetBufferByteSize(policy));
|
||||
policy.CipherResynchronize(m_buffer, iv);
|
||||
}
|
||||
|
||||
template <class BASE>
|
||||
void AdditiveCipherTemplate<BASE>::Seek(dword position)
|
||||
{
|
||||
PolicyInterface &policy = AccessPolicy();
|
||||
unsigned int bytesPerIteration = policy.GetBytesPerIteration();
|
||||
|
||||
policy.SeekToIteration(position / bytesPerIteration);
|
||||
position %= bytesPerIteration;
|
||||
|
||||
if (position > 0)
|
||||
{
|
||||
policy.WriteKeystream(m_buffer, 1);
|
||||
m_leftOver = bytesPerIteration - (unsigned int)position;
|
||||
}
|
||||
else
|
||||
m_leftOver = 0;
|
||||
}
|
||||
|
||||
template <class BASE>
|
||||
void CFB_CipherTemplate<BASE>::Resynchronize(const byte *iv)
|
||||
{
|
||||
PolicyInterface &policy = AccessPolicy();
|
||||
policy.CipherResynchronize(iv);
|
||||
m_leftOver = policy.GetBytesPerIteration();
|
||||
}
|
||||
|
||||
template <class BASE>
|
||||
void CFB_CipherTemplate<BASE>::ProcessData(byte *outString, const byte *inString, unsigned int length)
|
||||
{
|
||||
PolicyInterface &policy = AccessPolicy();
|
||||
unsigned int bytesPerIteration = policy.GetBytesPerIteration();
|
||||
unsigned int alignment = policy.GetAlignment();
|
||||
byte *reg = policy.GetRegisterBegin();
|
||||
|
||||
if (m_leftOver)
|
||||
{
|
||||
unsigned int len = STDMIN(m_leftOver, length);
|
||||
CombineMessageAndShiftRegister(outString, reg + bytesPerIteration - m_leftOver, inString, len);
|
||||
m_leftOver -= len;
|
||||
length -= len;
|
||||
inString += len;
|
||||
outString += len;
|
||||
}
|
||||
|
||||
if (!length)
|
||||
return;
|
||||
|
||||
assert(m_leftOver == 0);
|
||||
|
||||
if (policy.CanIterate() && length >= bytesPerIteration && IsAlignedOn(outString, alignment))
|
||||
{
|
||||
if (IsAlignedOn(inString, alignment))
|
||||
policy.Iterate(outString, inString, GetCipherDir(*this), length / bytesPerIteration);
|
||||
else
|
||||
{
|
||||
memcpy(outString, inString, length);
|
||||
policy.Iterate(outString, outString, GetCipherDir(*this), length / bytesPerIteration);
|
||||
}
|
||||
inString += length - length % bytesPerIteration;
|
||||
outString += length - length % bytesPerIteration;
|
||||
length %= bytesPerIteration;
|
||||
}
|
||||
|
||||
while (length >= bytesPerIteration)
|
||||
{
|
||||
policy.TransformRegister();
|
||||
CombineMessageAndShiftRegister(outString, reg, inString, bytesPerIteration);
|
||||
length -= bytesPerIteration;
|
||||
inString += bytesPerIteration;
|
||||
outString += bytesPerIteration;
|
||||
}
|
||||
|
||||
if (length > 0)
|
||||
{
|
||||
policy.TransformRegister();
|
||||
CombineMessageAndShiftRegister(outString, reg, inString, length);
|
||||
m_leftOver = bytesPerIteration - length;
|
||||
}
|
||||
}
|
||||
|
||||
template <class BASE>
|
||||
void CFB_EncryptionTemplate<BASE>::CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, unsigned int length)
|
||||
{
|
||||
xorbuf(reg, message, length);
|
||||
memcpy(output, reg, length);
|
||||
}
|
||||
|
||||
template <class BASE>
|
||||
void CFB_DecryptionTemplate<BASE>::CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, unsigned int length)
|
||||
{
|
||||
for (unsigned int i=0; i<length; i++)
|
||||
{
|
||||
byte b = message[i];
|
||||
output[i] = reg[i] ^ b;
|
||||
reg[i] = b;
|
||||
}
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
@@ -0,0 +1,288 @@
|
||||
/*! \file
|
||||
This file contains helper classes for implementing stream ciphers.
|
||||
|
||||
All this infrastructure may look very complex compared to what's in Crypto++ 4.x,
|
||||
but stream ciphers implementations now support a lot of new functionality,
|
||||
including better performance (minimizing copying), resetting of keys and IVs, and methods to
|
||||
query which features are supported by a cipher.
|
||||
|
||||
Here's an explanation of these classes. The word "policy" is used here to mean a class with a
|
||||
set of methods that must be implemented by individual stream cipher implementations.
|
||||
This is usually much simpler than the full stream cipher API, which is implemented by
|
||||
either AdditiveCipherTemplate or CFB_CipherTemplate using the policy. So for example, an
|
||||
implementation of SEAL only needs to implement the AdditiveCipherAbstractPolicy interface
|
||||
(since it's an additive cipher, i.e., it xors a keystream into the plaintext).
|
||||
See this line in seal.h:
|
||||
|
||||
typedef SymmetricCipherFinalTemplate<ConcretePolicyHolder<SEAL_Policy<B>, AdditiveCipherTemplate<> > > Encryption;
|
||||
|
||||
AdditiveCipherTemplate and CFB_CipherTemplate are designed so that they don't need
|
||||
to take a policy class as a template parameter (although this is allowed), so that
|
||||
their code is not duplicated for each new cipher. Instead they each
|
||||
get a reference to an abstract policy interface by calling AccessPolicy() on itself, so
|
||||
AccessPolicy() must be overriden to return the actual policy reference. This is done
|
||||
by the ConceretePolicyHolder class. Finally, SymmetricCipherFinalTemplate implements the constructors and
|
||||
other functions that must be implemented by the most derived class.
|
||||
*/
|
||||
|
||||
#ifndef CRYPTOPP_STRCIPHR_H
|
||||
#define CRYPTOPP_STRCIPHR_H
|
||||
|
||||
#include "seckey.h"
|
||||
#include "secblock.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
template <class POLICY_INTERFACE, class BASE = Empty>
|
||||
class AbstractPolicyHolder : public BASE
|
||||
{
|
||||
public:
|
||||
typedef POLICY_INTERFACE PolicyInterface;
|
||||
|
||||
protected:
|
||||
virtual const POLICY_INTERFACE & GetPolicy() const =0;
|
||||
virtual POLICY_INTERFACE & AccessPolicy() =0;
|
||||
};
|
||||
|
||||
template <class POLICY, class BASE, class POLICY_INTERFACE = CPP_TYPENAME BASE::PolicyInterface>
|
||||
class ConcretePolicyHolder : public BASE, protected POLICY
|
||||
{
|
||||
protected:
|
||||
const POLICY_INTERFACE & GetPolicy() const {return *this;}
|
||||
POLICY_INTERFACE & AccessPolicy() {return *this;}
|
||||
};
|
||||
|
||||
enum KeystreamOperation {WRITE_KEYSTREAM, XOR_KEYSTREAM, XOR_KEYSTREAM_INPLACE};
|
||||
|
||||
struct AdditiveCipherAbstractPolicy
|
||||
{
|
||||
virtual unsigned int GetAlignment() const =0;
|
||||
virtual unsigned int GetBytesPerIteration() const =0;
|
||||
virtual unsigned int GetIterationsToBuffer() const =0;
|
||||
virtual void WriteKeystream(byte *keystreamBuffer, unsigned int iterationCount) =0;
|
||||
virtual bool CanOperateKeystream() const {return false;}
|
||||
virtual void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, unsigned int iterationCount) {assert(false);}
|
||||
virtual void CipherSetKey(const NameValuePairs ¶ms, const byte *key, unsigned int length) =0;
|
||||
virtual void CipherResynchronize(byte *keystreamBuffer, const byte *iv) {throw NotImplemented("StreamTransformation: this object doesn't support resynchronization");}
|
||||
virtual bool IsRandomAccess() const =0;
|
||||
virtual void SeekToIteration(dword iterationCount) {assert(!IsRandomAccess()); throw NotImplemented("StreamTransformation: this object doesn't support random access");}
|
||||
};
|
||||
|
||||
template <typename WT, unsigned int W, unsigned int X = 1, class BASE = AdditiveCipherAbstractPolicy>
|
||||
struct AdditiveCipherConcretePolicy : public BASE
|
||||
{
|
||||
typedef WT WordType;
|
||||
|
||||
unsigned int GetAlignment() const {return sizeof(WordType);}
|
||||
unsigned int GetBytesPerIteration() const {return sizeof(WordType) * W;}
|
||||
unsigned int GetIterationsToBuffer() const {return X;}
|
||||
void WriteKeystream(byte *buffer, unsigned int iterationCount)
|
||||
{OperateKeystream(WRITE_KEYSTREAM, buffer, NULL, iterationCount);}
|
||||
bool CanOperateKeystream() const {return true;}
|
||||
virtual void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, unsigned int iterationCount) =0;
|
||||
|
||||
template <class B>
|
||||
struct KeystreamOutput
|
||||
{
|
||||
KeystreamOutput(KeystreamOperation operation, byte *output, const byte *input)
|
||||
: m_operation(operation), m_output(output), m_input(input) {}
|
||||
|
||||
inline KeystreamOutput & operator()(WordType keystreamWord)
|
||||
{
|
||||
assert(IsAligned<WordType>(m_input));
|
||||
assert(IsAligned<WordType>(m_output));
|
||||
|
||||
if (!NativeByteOrderIs(B::ToEnum()))
|
||||
keystreamWord = ByteReverse(keystreamWord);
|
||||
|
||||
if (m_operation == WRITE_KEYSTREAM)
|
||||
*(WordType*)m_output = keystreamWord;
|
||||
else if (m_operation == XOR_KEYSTREAM)
|
||||
{
|
||||
*(WordType*)m_output = keystreamWord ^ *(WordType*)m_input;
|
||||
m_input += sizeof(WordType);
|
||||
}
|
||||
else if (m_operation == XOR_KEYSTREAM_INPLACE)
|
||||
*(WordType*)m_output ^= keystreamWord;
|
||||
|
||||
m_output += sizeof(WordType);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
KeystreamOperation m_operation;
|
||||
byte *m_output;
|
||||
const byte *m_input;
|
||||
};
|
||||
};
|
||||
|
||||
template <class BASE = AbstractPolicyHolder<AdditiveCipherAbstractPolicy, TwoBases<SymmetricCipher, RandomNumberGenerator> > >
|
||||
class AdditiveCipherTemplate : public BASE
|
||||
{
|
||||
public:
|
||||
byte GenerateByte();
|
||||
void ProcessData(byte *outString, const byte *inString, unsigned int length);
|
||||
void Resynchronize(const byte *iv);
|
||||
unsigned int OptimalBlockSize() const {return GetPolicy().GetBytesPerIteration();}
|
||||
unsigned int GetOptimalNextBlockSize() const {return m_leftOver;}
|
||||
unsigned int OptimalDataAlignment() const {return GetPolicy().GetAlignment();}
|
||||
bool IsSelfInverting() const {return true;}
|
||||
bool IsForwardTransformation() const {return true;}
|
||||
bool IsRandomAccess() const {return GetPolicy().IsRandomAccess();}
|
||||
void Seek(dword position);
|
||||
|
||||
typedef typename BASE::PolicyInterface PolicyInterface;
|
||||
|
||||
protected:
|
||||
void UncheckedSetKey(const NameValuePairs ¶ms, const byte *key, unsigned int length);
|
||||
|
||||
unsigned int GetBufferByteSize(const PolicyInterface &policy) const {return policy.GetBytesPerIteration() * policy.GetIterationsToBuffer();}
|
||||
|
||||
inline byte * KeystreamBufferBegin() {return m_buffer.data();}
|
||||
inline byte * KeystreamBufferEnd() {return (m_buffer.data() + m_buffer.size());}
|
||||
|
||||
SecByteBlock m_buffer;
|
||||
unsigned int m_leftOver;
|
||||
};
|
||||
|
||||
struct CFB_CipherAbstractPolicy
|
||||
{
|
||||
virtual unsigned int GetAlignment() const =0;
|
||||
virtual unsigned int GetBytesPerIteration() const =0;
|
||||
virtual byte * GetRegisterBegin() =0;
|
||||
virtual void TransformRegister() =0;
|
||||
virtual bool CanIterate() const {return false;}
|
||||
virtual void Iterate(byte *output, const byte *input, CipherDir dir, unsigned int iterationCount) {assert(false);}
|
||||
virtual void CipherSetKey(const NameValuePairs ¶ms, const byte *key, unsigned int length) =0;
|
||||
virtual void CipherResynchronize(const byte *iv) {throw NotImplemented("StreamTransformation: this object doesn't support resynchronization");}
|
||||
};
|
||||
|
||||
template <typename WT, unsigned int W, class BASE = CFB_CipherAbstractPolicy>
|
||||
struct CFB_CipherConcretePolicy : public BASE
|
||||
{
|
||||
typedef WT WordType;
|
||||
|
||||
unsigned int GetAlignment() const {return sizeof(WordType);}
|
||||
unsigned int GetBytesPerIteration() const {return sizeof(WordType) * W;}
|
||||
bool CanIterate() const {return true;}
|
||||
void TransformRegister() {Iterate(NULL, NULL, ENCRYPTION, 1);}
|
||||
|
||||
template <class B>
|
||||
struct RegisterOutput
|
||||
{
|
||||
RegisterOutput(byte *output, const byte *input, CipherDir dir)
|
||||
: m_output(output), m_input(input), m_dir(dir) {}
|
||||
|
||||
inline RegisterOutput& operator()(WordType ®isterWord)
|
||||
{
|
||||
assert(IsAligned<WordType>(m_output));
|
||||
assert(IsAligned<WordType>(m_input));
|
||||
|
||||
if (!NativeByteOrderIs(B::ToEnum()))
|
||||
registerWord = ByteReverse(registerWord);
|
||||
|
||||
if (m_dir == ENCRYPTION)
|
||||
{
|
||||
WordType ct = *(const WordType *)m_input ^ registerWord;
|
||||
registerWord = ct;
|
||||
*(WordType*)m_output = ct;
|
||||
m_input += sizeof(WordType);
|
||||
m_output += sizeof(WordType);
|
||||
}
|
||||
else
|
||||
{
|
||||
WordType ct = *(const WordType *)m_input;
|
||||
*(WordType*)m_output = registerWord ^ ct;
|
||||
registerWord = ct;
|
||||
m_input += sizeof(WordType);
|
||||
m_output += sizeof(WordType);
|
||||
}
|
||||
|
||||
// registerWord is left unreversed so it can be xor-ed with further input
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
byte *m_output;
|
||||
const byte *m_input;
|
||||
CipherDir m_dir;
|
||||
};
|
||||
};
|
||||
|
||||
template <class BASE>
|
||||
class CFB_CipherTemplate : public BASE
|
||||
{
|
||||
public:
|
||||
void ProcessData(byte *outString, const byte *inString, unsigned int length);
|
||||
void Resynchronize(const byte *iv);
|
||||
unsigned int OptimalBlockSize() const {return GetPolicy().GetBytesPerIteration();}
|
||||
unsigned int GetOptimalNextBlockSize() const {return m_leftOver;}
|
||||
unsigned int OptimalDataAlignment() const {return GetPolicy().GetAlignment();}
|
||||
bool IsRandomAccess() const {return false;}
|
||||
bool IsSelfInverting() const {return false;}
|
||||
|
||||
typedef typename BASE::PolicyInterface PolicyInterface;
|
||||
|
||||
protected:
|
||||
virtual void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, unsigned int length) =0;
|
||||
|
||||
void UncheckedSetKey(const NameValuePairs ¶ms, const byte *key, unsigned int length);
|
||||
|
||||
unsigned int m_leftOver;
|
||||
};
|
||||
|
||||
template <class BASE = AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >
|
||||
class CFB_EncryptionTemplate : public CFB_CipherTemplate<BASE>
|
||||
{
|
||||
bool IsForwardTransformation() const {return true;}
|
||||
void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, unsigned int length);
|
||||
};
|
||||
|
||||
template <class BASE = AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >
|
||||
class CFB_DecryptionTemplate : public CFB_CipherTemplate<BASE>
|
||||
{
|
||||
bool IsForwardTransformation() const {return false;}
|
||||
void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, unsigned int length);
|
||||
};
|
||||
|
||||
template <class BASE, class INFO = BASE>
|
||||
class SymmetricCipherFinalTemplate : public AlgorithmImpl<SimpleKeyingInterfaceImpl<BASE, INFO>, INFO>
|
||||
{
|
||||
public:
|
||||
SymmetricCipherFinalTemplate() {}
|
||||
SymmetricCipherFinalTemplate(const byte *key)
|
||||
{SetKey(key, DEFAULT_KEYLENGTH);}
|
||||
SymmetricCipherFinalTemplate(const byte *key, unsigned int length)
|
||||
{SetKey(key, length);}
|
||||
SymmetricCipherFinalTemplate(const byte *key, unsigned int length, const byte *iv)
|
||||
{SetKey(key, length); Resynchronize(iv);}
|
||||
|
||||
void SetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms = g_nullNameValuePairs)
|
||||
{
|
||||
ThrowIfInvalidKeyLength(length);
|
||||
UncheckedSetKey(params, key, length);
|
||||
}
|
||||
|
||||
Clonable * Clone() const {return static_cast<SymmetricCipher *>(new SymmetricCipherFinalTemplate<BASE, INFO>(*this));}
|
||||
};
|
||||
|
||||
template <class S>
|
||||
void AdditiveCipherTemplate<S>::UncheckedSetKey(const NameValuePairs ¶ms, const byte *key, unsigned int length)
|
||||
{
|
||||
PolicyInterface &policy = AccessPolicy();
|
||||
policy.CipherSetKey(params, key, length);
|
||||
m_buffer.New(GetBufferByteSize(policy));
|
||||
m_leftOver = 0;
|
||||
}
|
||||
|
||||
template <class BASE>
|
||||
void CFB_CipherTemplate<BASE>::UncheckedSetKey(const NameValuePairs ¶ms, const byte *key, unsigned int length)
|
||||
{
|
||||
PolicyInterface &policy = AccessPolicy();
|
||||
policy.CipherSetKey(params, key, length);
|
||||
m_leftOver = policy.GetBytesPerIteration();
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,166 @@
|
||||
// test.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "sha.h"
|
||||
#include "files.h"
|
||||
#include "rng.h"
|
||||
#include "rsa.h"
|
||||
#include "randpool.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef CRYPTOPP_WIN32_AVAILABLE
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#if (_MSC_VER >= 1000)
|
||||
#include <crtdbg.h> // for the debug heap
|
||||
#endif
|
||||
|
||||
#if defined(__MWERKS__) && defined(macintosh)
|
||||
#include <console.h>
|
||||
#endif
|
||||
|
||||
USING_NAMESPACE(CryptoPP)
|
||||
USING_NAMESPACE(std)
|
||||
|
||||
void GenerateRSAKey(unsigned int keyLength, const char *privFilename, const char *pubFilename, const char *seed);
|
||||
string RSAEncryptString(const char *pubFilename, const char *seed, const char *message);
|
||||
string RSADecryptString(const char *privFilename, const char *ciphertext);
|
||||
void RSASignFile(const char *privFilename, const char *messageFilename, const char *signatureFilename);
|
||||
bool RSAVerifyFile(const char *pubFilename, const char *messageFilename, const char *signatureFilename);
|
||||
|
||||
int (*AdhocTest)(int argc, char *argv[]) = NULL;
|
||||
|
||||
#ifdef __BCPLUSPLUS__
|
||||
int cmain(int argc, char *argv[])
|
||||
#elif defined(_MSC_VER)
|
||||
int __cdecl main(int argc, char *argv[])
|
||||
#else
|
||||
int main(int argc, char *argv[])
|
||||
#endif
|
||||
{
|
||||
#ifdef _CRTDBG_LEAK_CHECK_DF
|
||||
// Turn on leak-checking
|
||||
int tempflag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
|
||||
tempflag |= _CRTDBG_LEAK_CHECK_DF;
|
||||
_CrtSetDbgFlag( tempflag );
|
||||
#endif
|
||||
|
||||
#if defined(__MWERKS__) && defined(macintosh)
|
||||
argc = ccommand(&argv);
|
||||
#endif
|
||||
|
||||
try
|
||||
{
|
||||
std::string command, executableName, edcFilename;
|
||||
|
||||
if (argc < 2)
|
||||
command = 'h';
|
||||
else
|
||||
command = argv[1];
|
||||
|
||||
switch (command[0])
|
||||
{
|
||||
case 'g':
|
||||
{
|
||||
char seed[1024], privFilename[128], pubFilename[128];
|
||||
unsigned int keyLength;
|
||||
|
||||
cout << "Key length in bits: ";
|
||||
cin >> keyLength;
|
||||
|
||||
cout << "\nSave private key to file: ";
|
||||
cin >> privFilename;
|
||||
|
||||
cout << "\nSave public key to file: ";
|
||||
cin >> pubFilename;
|
||||
|
||||
cout << "\nRandom Seed: ";
|
||||
ws(cin);
|
||||
cin.getline(seed, 1024);
|
||||
|
||||
GenerateRSAKey(keyLength, privFilename, pubFilename, seed);
|
||||
return 0;
|
||||
}
|
||||
case 'r':
|
||||
{
|
||||
switch (argv[1][1])
|
||||
{
|
||||
case 's':
|
||||
RSASignFile(argv[2], argv[3], argv[4]);
|
||||
return 0;
|
||||
case 'v':
|
||||
{
|
||||
bool verified = RSAVerifyFile(argv[2], argv[3], argv[4]);
|
||||
cout << (verified ? "valid signature" : "invalid signature") << endl;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
FileSource usage("usage.dat", true, new FileSink(cout));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
catch(CryptoPP::Exception &e)
|
||||
{
|
||||
cout << "\nCryptoPP::Exception caught: " << e.what() << endl;
|
||||
return -1;
|
||||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
cout << "\nstd::exception caught: " << e.what() << endl;
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
RandomPool & GlobalRNG()
|
||||
{
|
||||
static RandomPool randomPool;
|
||||
return randomPool;
|
||||
}
|
||||
|
||||
void GenerateRSAKey(unsigned int keyLength, const char *privFilename, const char *pubFilename, const char *seed)
|
||||
{
|
||||
RandomPool randPool;
|
||||
randPool.Put((byte *)seed, strlen(seed));
|
||||
|
||||
RSAES_PKCS1v15_Decryptor priv(randPool, keyLength);
|
||||
FileSink privFile(privFilename);
|
||||
priv.DEREncode(privFile);
|
||||
privFile.MessageEnd();
|
||||
|
||||
RSAES_PKCS1v15_Encryptor pub(priv);
|
||||
FileSink pubFile(pubFilename);
|
||||
pub.DEREncode(pubFile);
|
||||
pubFile.MessageEnd();
|
||||
}
|
||||
|
||||
void RSASignFile(const char *privFilename, const char *messageFilename, const char *signatureFilename)
|
||||
{
|
||||
FileSource privFile(privFilename, true);
|
||||
RSASSA_PKCS1v15_SHA_Signer priv(privFile);
|
||||
// RSASSA_PKCS1v15_SHA_Signer ignores the rng. Use a real RNG for other signature schemes!
|
||||
FileSource f(messageFilename, true, new SignerFilter(GlobalRNG(), priv, new FileSink(signatureFilename)));
|
||||
}
|
||||
|
||||
bool RSAVerifyFile(const char *pubFilename, const char *messageFilename, const char *signatureFilename)
|
||||
{
|
||||
FileSource pubFile(pubFilename, true);
|
||||
RSASSA_PKCS1v15_SHA_Verifier pub(pubFile);
|
||||
|
||||
FileSource signatureFile(signatureFilename, true);
|
||||
if (signatureFile.MaxRetrievable() != pub.SignatureLength())
|
||||
return false;
|
||||
SecByteBlock signature(pub.SignatureLength());
|
||||
signatureFile.Get(signature, signature.size());
|
||||
|
||||
VerifierFilter *verifierFilter = new VerifierFilter(pub);
|
||||
verifierFilter->Put(signature, pub.SignatureLength());
|
||||
FileSource f(messageFilename, true, verifierFilter);
|
||||
|
||||
return verifierFilter->GetLastResult();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
#ifndef CRYPTOPP_TRDLOCAL_H
|
||||
#define CRYPTOPP_TRDLOCAL_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef THREADS_AVAILABLE
|
||||
|
||||
#include "misc.h"
|
||||
|
||||
#ifdef HAS_WINTHREADS
|
||||
#include <windows.h>
|
||||
typedef DWORD ThreadLocalIndexType;
|
||||
#else
|
||||
#include <pthread.h>
|
||||
typedef pthread_key_t ThreadLocalIndexType;
|
||||
#endif
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
//! thread local storage
|
||||
class ThreadLocalStorage : public NotCopyable
|
||||
{
|
||||
public:
|
||||
//! exception thrown by ThreadLocalStorage class
|
||||
class Err : public OS_Error
|
||||
{
|
||||
public:
|
||||
Err(const std::string& operation, int error);
|
||||
};
|
||||
|
||||
ThreadLocalStorage();
|
||||
~ThreadLocalStorage();
|
||||
|
||||
void SetValue(void *value);
|
||||
void *GetValue() const;
|
||||
|
||||
private:
|
||||
ThreadLocalIndexType m_index;
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif // #ifdef THREADS_AVAILABLE
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,103 @@
|
||||
#ifndef CRYPTOPP_WORDS_H
|
||||
#define CRYPTOPP_WORDS_H
|
||||
|
||||
#include "misc.h"
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
inline unsigned int CountWords(const word *X, unsigned int N)
|
||||
{
|
||||
while (N && X[N-1]==0)
|
||||
N--;
|
||||
return N;
|
||||
}
|
||||
|
||||
inline void SetWords(word *r, word a, unsigned int n)
|
||||
{
|
||||
for (unsigned int i=0; i<n; i++)
|
||||
r[i] = a;
|
||||
}
|
||||
|
||||
inline void CopyWords(word *r, const word *a, unsigned int n)
|
||||
{
|
||||
for (unsigned int i=0; i<n; i++)
|
||||
r[i] = a[i];
|
||||
}
|
||||
|
||||
inline void XorWords(word *r, const word *a, const word *b, unsigned int n)
|
||||
{
|
||||
for (unsigned int i=0; i<n; i++)
|
||||
r[i] = a[i] ^ b[i];
|
||||
}
|
||||
|
||||
inline void XorWords(word *r, const word *a, unsigned int n)
|
||||
{
|
||||
for (unsigned int i=0; i<n; i++)
|
||||
r[i] ^= a[i];
|
||||
}
|
||||
|
||||
inline void AndWords(word *r, const word *a, const word *b, unsigned int n)
|
||||
{
|
||||
for (unsigned int i=0; i<n; i++)
|
||||
r[i] = a[i] & b[i];
|
||||
}
|
||||
|
||||
inline void AndWords(word *r, const word *a, unsigned int n)
|
||||
{
|
||||
for (unsigned int i=0; i<n; i++)
|
||||
r[i] &= a[i];
|
||||
}
|
||||
|
||||
inline word ShiftWordsLeftByBits(word *r, unsigned int n, unsigned int shiftBits)
|
||||
{
|
||||
assert (shiftBits<WORD_BITS);
|
||||
word u, carry=0;
|
||||
if (shiftBits)
|
||||
for (unsigned int i=0; i<n; i++)
|
||||
{
|
||||
u = r[i];
|
||||
r[i] = (u << shiftBits) | carry;
|
||||
carry = u >> (WORD_BITS-shiftBits);
|
||||
}
|
||||
return carry;
|
||||
}
|
||||
|
||||
inline word ShiftWordsRightByBits(word *r, unsigned int n, unsigned int shiftBits)
|
||||
{
|
||||
assert (shiftBits<WORD_BITS);
|
||||
word u, carry=0;
|
||||
if (shiftBits)
|
||||
for (int i=n-1; i>=0; i--)
|
||||
{
|
||||
u = r[i];
|
||||
r[i] = (u >> shiftBits) | carry;
|
||||
carry = u << (WORD_BITS-shiftBits);
|
||||
}
|
||||
return carry;
|
||||
}
|
||||
|
||||
inline void ShiftWordsLeftByWords(word *r, unsigned int n, unsigned int shiftWords)
|
||||
{
|
||||
shiftWords = STDMIN(shiftWords, n);
|
||||
if (shiftWords)
|
||||
{
|
||||
for (unsigned int i=n-1; i>=shiftWords; i--)
|
||||
r[i] = r[i-shiftWords];
|
||||
SetWords(r, 0, shiftWords);
|
||||
}
|
||||
}
|
||||
|
||||
inline void ShiftWordsRightByWords(word *r, unsigned int n, unsigned int shiftWords)
|
||||
{
|
||||
shiftWords = STDMIN(shiftWords, n);
|
||||
if (shiftWords)
|
||||
{
|
||||
for (unsigned int i=0; i+shiftWords<n; i++)
|
||||
r[i] = r[i+shiftWords];
|
||||
SetWords(r+n-shiftWords, 0, shiftWords);
|
||||
}
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,102 @@
|
||||
// Based on test.cpp from crypto++
|
||||
// Parameters:
|
||||
// public_key - X.509 standard SubjectPublicKeyInfo key in binary format
|
||||
// data_file - the data file whose signature to verify
|
||||
// signature - the signature of data_file in binary format
|
||||
// test.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "sha.h"
|
||||
#include "files.h"
|
||||
#include "rsa.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef CRYPTOPP_WIN32_AVAILABLE
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#if (_MSC_VER >= 1000)
|
||||
#include <crtdbg.h> // for the debug heap
|
||||
#endif
|
||||
|
||||
#if defined(__MWERKS__) && defined(macintosh)
|
||||
#include <console.h>
|
||||
#endif
|
||||
|
||||
USING_NAMESPACE(CryptoPP)
|
||||
USING_NAMESPACE(std)
|
||||
|
||||
bool RSAVerifyFile(const char *pubFilename, const char *messageFilename, const char *signatureFilename);
|
||||
|
||||
int (*AdhocTest)(int argc, char *argv[]) = NULL;
|
||||
|
||||
#ifdef __BCPLUSPLUS__
|
||||
int cmain(int argc, char *argv[])
|
||||
#elif defined(_MSC_VER)
|
||||
int __cdecl main(int argc, char *argv[])
|
||||
#else
|
||||
int main(int argc, char *argv[])
|
||||
#endif
|
||||
{
|
||||
#ifdef _CRTDBG_LEAK_CHECK_DF
|
||||
// Turn on leak-checking
|
||||
int tempflag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
|
||||
tempflag |= _CRTDBG_LEAK_CHECK_DF;
|
||||
_CrtSetDbgFlag( tempflag );
|
||||
#endif
|
||||
|
||||
#if defined(__MWERKS__) && defined(macintosh)
|
||||
argc = ccommand(&argv);
|
||||
#endif
|
||||
|
||||
try
|
||||
{
|
||||
std::string command, executableName, edcFilename;
|
||||
|
||||
if (argc != 4)
|
||||
{
|
||||
cout << "\nUsage: RSAPubKeyData.exe publickey_fn data_fn signature_fn" << endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( RSAVerifyFile(argv[2], argv[3], argv[4]) )
|
||||
{
|
||||
cout << "The signature is valid." << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << "The signature is not valid." << endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
catch(CryptoPP::Exception &e)
|
||||
{
|
||||
cout << "\nCryptoPP::Exception caught: " << e.what() << endl;
|
||||
return -1;
|
||||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
cout << "\nstd::exception caught: " << e.what() << endl;
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
bool RSAVerifyFile(const char *pubFilename, const char *messageFilename, const char *signatureFilename)
|
||||
{
|
||||
FileSource pubFile(pubFilename, true);
|
||||
RSASSA_PKCS1v15_SHA_Verifier pub(pubFile);
|
||||
|
||||
FileSource signatureFile(signatureFilename, true);
|
||||
if (signatureFile.MaxRetrievable() != pub.SignatureLength())
|
||||
return false;
|
||||
SecByteBlock signature(pub.SignatureLength());
|
||||
signatureFile.Get(signature, signature.size());
|
||||
|
||||
VerifierFilter *verifierFilter = new VerifierFilter(pub);
|
||||
verifierFilter->Put(signature, pub.SignatureLength());
|
||||
FileSource f(messageFilename, true, verifierFilter);
|
||||
|
||||
return verifierFilter->GetLastResult();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,395 @@
|
||||
// Based on http://www.jensign.com/VerifySignature/dotnet/JKeyNet/
|
||||
// Parameters:
|
||||
// public_key - X.509 standard SubjectPublicKeyInfo key in binary format
|
||||
// data_file - the data file whose signature to verify
|
||||
// signature - the signature of data_file in binary format
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Security;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace VerifySignature
|
||||
{
|
||||
|
||||
//--- P/Invoke CryptoAPI wrapper classes -----
|
||||
public class Win32
|
||||
{
|
||||
|
||||
[DllImport("crypt32.dll")]
|
||||
public static extern bool CryptDecodeObject(
|
||||
uint CertEncodingType,
|
||||
uint lpszStructType,
|
||||
byte[] pbEncoded,
|
||||
uint cbEncoded,
|
||||
uint flags,
|
||||
[In, Out] byte[] pvStructInfo,
|
||||
ref uint cbStructInfo);
|
||||
|
||||
|
||||
[DllImport("crypt32.dll")]
|
||||
public static extern bool CryptDecodeObject(
|
||||
uint CertEncodingType,
|
||||
uint lpszStructType,
|
||||
byte[] pbEncoded,
|
||||
uint cbEncoded,
|
||||
uint flags,
|
||||
IntPtr pvStructInfo,
|
||||
ref uint cbStructInfo);
|
||||
}
|
||||
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct PUBKEYBLOBHEADERS
|
||||
{
|
||||
public byte bType; //BLOBHEADER
|
||||
public byte bVersion; //BLOBHEADER
|
||||
public short reserved; //BLOBHEADER
|
||||
public uint aiKeyAlg; //BLOBHEADER
|
||||
public uint magic; //RSAPUBKEY
|
||||
public uint bitlen; //RSAPUBKEY
|
||||
public uint pubexp; //RSAPUBKEY
|
||||
}
|
||||
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct CERT_PUBLIC_KEY_INFO
|
||||
{
|
||||
public IntPtr SubjPKIAlgpszObjId;
|
||||
public int SubjPKIAlgParameterscbData;
|
||||
public IntPtr SubjPKIAlgParameterspbData;
|
||||
public int PublicKeycbData;
|
||||
public IntPtr PublicKeypbData;
|
||||
public int PublicKeycUnusedBits;
|
||||
}
|
||||
|
||||
|
||||
public class RSAPubKeyData
|
||||
{
|
||||
|
||||
const uint X509_ASN_ENCODING = 0x00000001;
|
||||
const uint PKCS_7_ASN_ENCODING = 0x00010000;
|
||||
|
||||
const uint RSA_CSP_PUBLICKEYBLOB = 19;
|
||||
const uint X509_PUBLIC_KEY_INFO = 8;
|
||||
|
||||
const int AT_KEYEXCHANGE = 1; //keyspec values
|
||||
const int AT_SIGNATURE = 2;
|
||||
static uint ENCODING_TYPE = PKCS_7_ASN_ENCODING | X509_ASN_ENCODING ;
|
||||
|
||||
const byte PUBLICKEYBLOB = 0x06;
|
||||
const byte CUR_BLOB_VERSION = 0x02;
|
||||
const ushort reserved = 0x0000;
|
||||
const uint CALG_RSA_KEYX = 0x0000a400;
|
||||
const uint CALG_RSA_SIGN = 0x00002400;
|
||||
|
||||
|
||||
private byte[] keyModulus; // big-Endian
|
||||
private byte[] keyExponent; // big-Endian
|
||||
private byte[] publicKeyBlob; //Microsoft PUBLICKEYBLOB format
|
||||
private uint keySize; //modulus size in bits
|
||||
private bool verbose = false;
|
||||
|
||||
|
||||
public uint keysize
|
||||
{
|
||||
get{return keySize;}
|
||||
}
|
||||
|
||||
public byte[] keymodulus
|
||||
{
|
||||
get{return keyModulus;}
|
||||
}
|
||||
|
||||
public byte[] keyexponent
|
||||
{
|
||||
get{return keyExponent;}
|
||||
}
|
||||
|
||||
public byte[] MSpublickeyblob
|
||||
{
|
||||
get{return publicKeyBlob;}
|
||||
}
|
||||
|
||||
public static string readFile(string file)
|
||||
{
|
||||
string finalStr="";
|
||||
try
|
||||
{
|
||||
// Create an instance of StreamReader to read from a file.
|
||||
// The using statement also closes the StreamReader.
|
||||
using (StreamReader sr = new StreamReader(file))
|
||||
{
|
||||
String line;
|
||||
// Read and display lines from the file until the end of
|
||||
// the file is reached.
|
||||
while ((line = sr.ReadLine()) != null)
|
||||
{
|
||||
//Console.WriteLine(line);
|
||||
finalStr = finalStr+line;
|
||||
}
|
||||
return finalStr;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// Let the user know what went wrong.
|
||||
Console.WriteLine("The file could not be read:");
|
||||
Console.WriteLine(e.Message);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void Main(String[] args)
|
||||
{
|
||||
RSAPubKeyData orsakey = new RSAPubKeyData();
|
||||
|
||||
if(args.Length<3)
|
||||
{
|
||||
Console.WriteLine("\nUsage: RSAPubKeyData.exe public_key data_fn signature_fn");
|
||||
return;
|
||||
}
|
||||
|
||||
String publickeyfn = args[0];
|
||||
String datafn = args[1];
|
||||
String signaturefn = args[2];
|
||||
|
||||
if (!File.Exists(publickeyfn))
|
||||
{
|
||||
Console.WriteLine("File '{0}' not found.", publickeyfn);
|
||||
return;
|
||||
}
|
||||
if (!File.Exists(datafn))
|
||||
{
|
||||
Console.WriteLine("File '{0}' not found.", datafn);
|
||||
return;
|
||||
}
|
||||
if (!File.Exists(signaturefn))
|
||||
{
|
||||
Console.WriteLine("File '{0}' not found.", signaturefn);
|
||||
return;
|
||||
}
|
||||
|
||||
Console.WriteLine("\n\n-------- Trying to decode keyfile as X.509 SubjectPublicKeyInfo format --------");
|
||||
if(!orsakey.DecodeSubjectPublicKeyInfo(publickeyfn))
|
||||
{
|
||||
Console.WriteLine("FAILED to decode as X.509 SubjectPublicKeyInfo");
|
||||
return;
|
||||
}
|
||||
|
||||
Console.WriteLine("Decoded successfully as X.509 SubjectPublicKeyInfo");
|
||||
|
||||
RSAParameters RSAKeyInfo = new RSAParameters();
|
||||
RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
|
||||
|
||||
RSAKeyInfo.Modulus = orsakey.keymodulus;
|
||||
RSAKeyInfo.Exponent = orsakey.keyexponent;
|
||||
RSA.ImportParameters(RSAKeyInfo);
|
||||
|
||||
byte[] data = GetFileBytes(datafn);
|
||||
byte[] signature = GetFileBytes(signaturefn);
|
||||
|
||||
if(RSA.VerifyData(data,"SHA1",signature))
|
||||
{
|
||||
Console.WriteLine("The signature is valid.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("The signature is not valid.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---- RSAPublicKey, PKCS #1 format -----
|
||||
public bool DecodeRSAPublicKey(String RSAPublicKeyfile)
|
||||
{
|
||||
if (!File.Exists(RSAPublicKeyfile))
|
||||
return false;
|
||||
byte[] encodeddata = GetFileBytes(RSAPublicKeyfile);
|
||||
return DecodeRSAPublicKey(encodeddata);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//---- SubjectPublicKeyInfo, X.509 standard format; e.g. Java getEncoded(); OpenSSL exported etc.
|
||||
// --- decode first to RSAPublicKey encoded format ----
|
||||
public bool DecodeSubjectPublicKeyInfo(String SubjectPublicKeyInfoFile)
|
||||
{
|
||||
if (!File.Exists(SubjectPublicKeyInfoFile))
|
||||
return false;
|
||||
byte[] subjectpublickeydata = GetFileBytes(SubjectPublicKeyInfoFile);
|
||||
|
||||
IntPtr pcertpublickeyinfo = IntPtr.Zero ;
|
||||
uint cbytes=0;
|
||||
if(Win32.CryptDecodeObject(ENCODING_TYPE, X509_PUBLIC_KEY_INFO, subjectpublickeydata, (uint)subjectpublickeydata.Length, 0, IntPtr.Zero, ref cbytes))
|
||||
{
|
||||
pcertpublickeyinfo = Marshal.AllocHGlobal((int)cbytes);
|
||||
Win32.CryptDecodeObject(ENCODING_TYPE, X509_PUBLIC_KEY_INFO, subjectpublickeydata, (uint)subjectpublickeydata.Length, 0, pcertpublickeyinfo, ref cbytes);
|
||||
CERT_PUBLIC_KEY_INFO pkinfo = (CERT_PUBLIC_KEY_INFO) Marshal.PtrToStructure(pcertpublickeyinfo, typeof(CERT_PUBLIC_KEY_INFO) );
|
||||
IntPtr pencodeddata = pkinfo.PublicKeypbData;
|
||||
int cblob = pkinfo.PublicKeycbData ;
|
||||
byte[] encodeddata = new byte[cblob];
|
||||
Marshal.Copy(pencodeddata, encodeddata, 0,cblob) ; //copy bytes from IntPtr to byte[]
|
||||
Marshal.FreeHGlobal(pcertpublickeyinfo) ;
|
||||
return DecodeRSAPublicKey(encodeddata);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//----- decode public key and extract modulus and exponent from RSAPublicKey, PKCS #1 format byte[] ----
|
||||
public bool DecodeRSAPublicKey(byte[] encodedpubkey)
|
||||
{
|
||||
byte[] publickeyblob ;
|
||||
|
||||
uint blobbytes=0;
|
||||
if(Win32.CryptDecodeObject(ENCODING_TYPE, RSA_CSP_PUBLICKEYBLOB, encodedpubkey, (uint)encodedpubkey.Length, 0, null, ref blobbytes))
|
||||
{
|
||||
publickeyblob = new byte[blobbytes];
|
||||
if(Win32.CryptDecodeObject(ENCODING_TYPE, RSA_CSP_PUBLICKEYBLOB, encodedpubkey, (uint)encodedpubkey.Length, 0, publickeyblob, ref blobbytes))
|
||||
if(verbose)
|
||||
showBytes("CryptoAPI publickeyblob", publickeyblob);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
this.publicKeyBlob = publickeyblob;
|
||||
return DecodeMSPublicKeyBlob(publickeyblob);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//---- Microsoft PUBLICKEYBLOB format -----
|
||||
public bool DecodeMSPublicKeyBlob(String publickeyblobfile)
|
||||
{
|
||||
if (!File.Exists(publickeyblobfile))
|
||||
return false;
|
||||
byte[] publickeyblobdata = GetFileBytes(publickeyblobfile);
|
||||
return DecodeMSPublicKeyBlob(publickeyblobdata);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//----- Microsoft PUBLICKEYBLOB format ----
|
||||
public bool DecodeMSPublicKeyBlob(byte[] publickeyblob)
|
||||
{
|
||||
PUBKEYBLOBHEADERS pkheaders = new PUBKEYBLOBHEADERS() ;
|
||||
int headerslength = Marshal.SizeOf(pkheaders);
|
||||
IntPtr buffer = Marshal.AllocHGlobal( headerslength);
|
||||
Marshal.Copy( publickeyblob, 0, buffer, headerslength );
|
||||
pkheaders = (PUBKEYBLOBHEADERS) Marshal.PtrToStructure( buffer, typeof(PUBKEYBLOBHEADERS) );
|
||||
Marshal.FreeHGlobal( buffer );
|
||||
|
||||
//----- basic sanity check of PUBLICKEYBLOB fields ------------
|
||||
if(pkheaders.bType != PUBLICKEYBLOB)
|
||||
return false;
|
||||
if(pkheaders.bVersion != CUR_BLOB_VERSION)
|
||||
return false;
|
||||
if(pkheaders.aiKeyAlg != CALG_RSA_KEYX && pkheaders.aiKeyAlg != CALG_RSA_SIGN)
|
||||
return false;
|
||||
|
||||
if(verbose)
|
||||
{
|
||||
Console.WriteLine("\n ---- PUBLICKEYBLOB headers ------");
|
||||
Console.WriteLine(" btype {0}", pkheaders.bType);
|
||||
Console.WriteLine(" bversion {0}", pkheaders.bVersion);
|
||||
Console.WriteLine(" reserved {0}", pkheaders.reserved);
|
||||
Console.WriteLine(" aiKeyAlg 0x{0:x8}", pkheaders.aiKeyAlg);
|
||||
String magicstring = (new ASCIIEncoding()).GetString(BitConverter.GetBytes(pkheaders.magic)) ;
|
||||
Console.WriteLine(" magic 0x{0:x8} '{1}'", pkheaders.magic, magicstring);
|
||||
Console.WriteLine(" bitlen {0}", pkheaders.bitlen);
|
||||
Console.WriteLine(" pubexp {0}", pkheaders.pubexp);
|
||||
Console.WriteLine(" --------------------------------");
|
||||
}
|
||||
//----- Get public key size in bits -------------
|
||||
this.keySize = pkheaders.bitlen;
|
||||
|
||||
//----- Get public exponent -------------
|
||||
byte[] exponent = BitConverter.GetBytes(pkheaders.pubexp); //little-endian ordered
|
||||
Array.Reverse(exponent); //convert to big-endian order
|
||||
this.keyExponent = exponent;
|
||||
if(verbose)
|
||||
showBytes("\nPublic key exponent (big-endian order):", exponent);
|
||||
|
||||
//----- Get modulus -------------
|
||||
int modulusbytes = (int)pkheaders.bitlen/8 ;
|
||||
byte[] modulus = new byte[modulusbytes];
|
||||
try
|
||||
{
|
||||
Array.Copy(publickeyblob, headerslength, modulus, 0, modulusbytes);
|
||||
Array.Reverse(modulus); //convert from little to big-endian ordering.
|
||||
this.keyModulus = modulus;
|
||||
if(verbose)
|
||||
showBytes("\nPublic key modulus (big-endian order):", modulus);
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
Console.WriteLine("Problem getting modulus from publickeyblob");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private static byte[] GetFileBytes(String filename)
|
||||
{
|
||||
if(!File.Exists(filename))
|
||||
return null;
|
||||
Stream stream=new FileStream(filename,FileMode.Open);
|
||||
int datalen = (int)stream.Length;
|
||||
byte[] filebytes =new byte[datalen];
|
||||
stream.Seek(0,SeekOrigin.Begin);
|
||||
stream.Read(filebytes,0,datalen);
|
||||
stream.Close();
|
||||
return filebytes;
|
||||
}
|
||||
|
||||
|
||||
private void PutFileBytes(String outfile, byte[] data, int bytes)
|
||||
{
|
||||
FileStream fs = null;
|
||||
if(bytes > data.Length)
|
||||
{
|
||||
Console.WriteLine("Too many bytes");
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
fs = new FileStream(outfile, FileMode.Create);
|
||||
fs.Write(data, 0, bytes);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Console.WriteLine(e.Message) ;
|
||||
}
|
||||
finally
|
||||
{
|
||||
fs.Close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void showBytes(String info, byte[] data)
|
||||
{
|
||||
Console.WriteLine("{0} [{1} bytes]", info, data.Length);
|
||||
for(int i=1; i<=data.Length; i++)
|
||||
{
|
||||
Console.Write("{0:X2} ", data[i-1]) ;
|
||||
if(i%16 == 0)
|
||||
Console.WriteLine();
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,221 @@
|
||||
// Based on http://www.thecodeproject.com/useritems/Porting_Java_Public_Key.asp
|
||||
// Parameters:
|
||||
// public_key - X.509 standard SubjectPublicKeyInfo key in binary format
|
||||
// data_file - the data file whose signature to verify
|
||||
// signature - the signature of data_file in binary format
|
||||
|
||||
/** <p>Title: RSA Security</p>
|
||||
* Description: This class generates a RSA private and public key, reinstantiates
|
||||
* the keys from the corresponding key files.It also generates compatible .Net Public Key,
|
||||
* which we will read later in C# program using .Net Securtiy Framework
|
||||
* The reinstantiated keys are used to sign and verify the given data.</p>
|
||||
*
|
||||
* @author Shaheryar
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
import java.security.*;
|
||||
import java.security.spec.*;
|
||||
import java.io.*;
|
||||
import java.security.interfaces.*;
|
||||
import java.security.cert.*;
|
||||
import javax.xml.transform.stream.*;
|
||||
import javax.xml.transform.dom.*;
|
||||
import javax.xml.transform.*;
|
||||
import org.w3c.dom.*;
|
||||
import javax.xml.parsers.*;
|
||||
|
||||
public class VerifySignature {
|
||||
|
||||
private KeyPairGenerator keyGen; //Key pair generator for RSA
|
||||
public PrivateKey privateKey; // Private Key Class
|
||||
public PublicKey publicKey; // Public Key Class
|
||||
public KeyPair keypair; // KeyPair Class
|
||||
private Signature sign; // Signature, used to sign the data
|
||||
/**
|
||||
* Default Constructor. Instantiates the key paths and signature algorithm.
|
||||
*/
|
||||
public VerifySignature() {
|
||||
try {
|
||||
|
||||
//Get the instance of Signature Engine.
|
||||
sign = Signature.getInstance("SHA1withRSA");
|
||||
}
|
||||
catch (NoSuchAlgorithmException nsa) {
|
||||
System.out.println("" + nsa.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the public and private keys.
|
||||
*/
|
||||
private void initializePublicKey(String publickey_fn) {
|
||||
try {
|
||||
//Read key files back and decode them from BASE64
|
||||
byte[] publicKeyBytes = readKeyBytesFromFile(publickey_fn);
|
||||
|
||||
// Convert back to public and private key objects
|
||||
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
|
||||
EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicKeyBytes);
|
||||
publicKey = keyFactory.generatePublic(publicKeySpec);
|
||||
|
||||
}
|
||||
catch (IOException io) {
|
||||
System.out.println(
|
||||
"Public/ Private Key File Not found."+ io.getCause());
|
||||
}
|
||||
catch (InvalidKeySpecException e) {
|
||||
System.out.println(
|
||||
"Invalid Key Specs. Not valid Key files."+ e.getCause());
|
||||
}
|
||||
catch (NoSuchAlgorithmException e) {
|
||||
System.out.println(
|
||||
"There is no such algorithm. Please check the JDK ver."+ e.getCause());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies the signature for the given bytes using the public key.
|
||||
* @param signature Signature
|
||||
* @param data Data that was signed
|
||||
* @return boolean True if valid signature else false
|
||||
*/
|
||||
public boolean verifySignature(String publickey_fn, byte[] signature, byte[] data) {
|
||||
try {
|
||||
initializePublicKey(publickey_fn);
|
||||
sign.initVerify(publicKey);
|
||||
sign.update(data);
|
||||
return sign.verify(signature);
|
||||
}
|
||||
catch (SignatureException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (InvalidKeyException e) {
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the contents of the file in a byte array.
|
||||
* @param fileName File Name
|
||||
* @return byte[] Teh data read from a given file as a byte array.
|
||||
*/
|
||||
private byte[] readKeyBytesFromFile(String fileName) throws IOException{
|
||||
File file = new File(fileName);
|
||||
InputStream is = new FileInputStream(file);
|
||||
|
||||
// Get the size of the file
|
||||
long length = file.length();
|
||||
|
||||
// You cannot create an array using a long type.
|
||||
// It needs to be an int type.
|
||||
// Before converting to an int type, check
|
||||
// to ensure that file is not larger than Integer.MAX_VALUE.
|
||||
if (length > Integer.MAX_VALUE) {
|
||||
// File is too large
|
||||
}
|
||||
|
||||
// Create the byte array to hold the data
|
||||
byte[] bytes = new byte[ (int) length];
|
||||
|
||||
// Read in the bytes
|
||||
int offset = 0;
|
||||
int numRead = 0;
|
||||
while (offset < bytes.length
|
||||
&& (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) {
|
||||
offset += numRead;
|
||||
}
|
||||
|
||||
// Ensure all the bytes have been read in
|
||||
if (offset < bytes.length) {
|
||||
throw new IOException("Key File Error: Could not completely read file " + file.getName());
|
||||
}
|
||||
|
||||
// Close the input stream and return bytes
|
||||
is.close();
|
||||
return bytes;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static void main(String args[])
|
||||
{
|
||||
VerifySignature sm = new VerifySignature();
|
||||
|
||||
/*
|
||||
Uncomment next line for first time when you run the code,it will generate the keys.
|
||||
Afterwards,the application will read the generated key files from the given location.
|
||||
If you want to generate the key files each time, then you should keep it uncommented always.
|
||||
*/
|
||||
if( args.length != 3 )
|
||||
{
|
||||
System.out.println("\nUsage: RSAPubKeyData.exe publickey_fn data_fn signature_fn");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
String publickeyfn = args[0];
|
||||
String datafn = args[1];
|
||||
String signaturefn = args[2];
|
||||
|
||||
|
||||
byte[] data = sm.readBytesFromFile(datafn);
|
||||
byte[] signature = sm.readBytesFromFile(signaturefn);
|
||||
|
||||
if( sm.verifySignature(publickeyfn,signature,data) )
|
||||
{
|
||||
System.out.println("The signature is valid.");
|
||||
}
|
||||
else
|
||||
{
|
||||
System.out.println("The signature is not valid.");
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] readBytesFromFile(String fileName)
|
||||
{
|
||||
try
|
||||
{
|
||||
File file = new File(fileName);
|
||||
InputStream is = new FileInputStream(file);
|
||||
|
||||
// Get the size of the file
|
||||
long length = file.length();
|
||||
|
||||
// You cannot create an array using a long type.
|
||||
// It needs to be an int type.
|
||||
// Before converting to an int type, check
|
||||
// to ensure that file is not larger than Integer.MAX_VALUE.
|
||||
if (length > Integer.MAX_VALUE) {
|
||||
// File is too large
|
||||
}
|
||||
|
||||
// Create the byte array to hold the data
|
||||
byte[] bytes = new byte[ (int) length];
|
||||
|
||||
// Read in the bytes
|
||||
int offset = 0;
|
||||
int numRead = 0;
|
||||
while (offset < bytes.length
|
||||
&& (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) {
|
||||
offset += numRead;
|
||||
}
|
||||
|
||||
// Ensure all the bytes have been read in
|
||||
if (offset < bytes.length) {
|
||||
throw new IOException("Key File Error: Could not completely read file " + file.getName());
|
||||
}
|
||||
|
||||
// Close the input stream and return bytes
|
||||
is.close();
|
||||
return bytes;
|
||||
}catch(IOException ioe)
|
||||
{
|
||||
System.out.println("Exception occured while writing file"+ioe.getMessage());
|
||||
}
|
||||
byte[] bytes = new byte[ 1];
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user