Putty -> Crypto++

This commit is contained in:
Chris Danford
2004-05-13 06:02:32 +00:00
parent eb50104f37
commit 890cac4c24
95 changed files with 26262 additions and 143 deletions
+104 -143
View File
@@ -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.
+76
View File
@@ -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 $<
+67
View File
@@ -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.
+255
View File
@@ -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.
+340
View File
@@ -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
+275
View File
@@ -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
+10
View File
@@ -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
+325
View File
@@ -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 &copy)
: 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
+54
View File
@@ -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
+556
View File
@@ -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
+346
View File
@@ -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 &parameters) {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
+228
View File
@@ -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 &parameters)
{
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 &parameters)
{
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 &parameters)
{
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
+82
View File
@@ -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 &parameters);
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 &parameters);
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 &parameters);
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
+282
View File
@@ -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 &parameters/* =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
+91
View File
@@ -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 &parameters=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
+247
View File
@@ -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
+388
View File
@@ -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
+44
View File
@@ -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>
{{{
}}}
###############################################################################
+687
View File
@@ -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 &parameters, 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 &parameters, 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
+746
View File
@@ -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
+104
View File
@@ -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
+464
View File
@@ -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
+133
View File
@@ -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
+171
View File
@@ -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
+90
View File
@@ -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
+107
View File
@@ -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
+69
View File
@@ -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
+186
View File
@@ -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 &parameters)
{
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 &parameters)
{
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
+95
View File
@@ -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 &parameters);
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 &parameters);
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
+897
View File
@@ -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 &parameters, 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 &parameters, 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 &parameters)
{
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 &parameters, 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 &parameters)
{
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 &parameters)
{
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 &parameters, 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 &parameters)
{
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 &parameters, 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 &parameters)
{
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
+688
View File
@@ -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 &parameters=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 &parameters, 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 &parameters);
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 &parameters, unsigned int &firstSize, unsigned int &blockSize, unsigned int &lastSize)
{InitializeDerived(parameters);}
virtual void InitializeDerived(const NameValuePairs &parameters) {}
// 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 &parameters) {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 &parameters);
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 &parameters, 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 &parameters);
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 &parameters, 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 = &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 &parameters, 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 &parameters=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 &parameters=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 &parameters, 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 &parameters)
{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 &parameters = 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 &parameters);
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 &parameters);
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 &parameters) {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 &parameters) {}
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 &parameters)
{
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 &parameters)
{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
+79
View File
@@ -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
+47
View File
@@ -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
+42
View File
@@ -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
+32
View File
@@ -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 &parameters)
{
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
+36
View File
@@ -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 &parameters);
};
//! 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 &parameters) {}
private:
static const int *GetDecodingLookupArray();
};
NAMESPACE_END
#endif
File diff suppressed because it is too large Load Diff
+439
View File
@@ -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 &params = g_nullNameValuePairs);
void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &params = 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 &quotient, const Integer &dividend, 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
+122
View File
@@ -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
+121
View File
@@ -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
+115
View File
@@ -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
+24
View File
@@ -0,0 +1,24 @@
#ifndef CRYPTOPP_MD5_H
#define CRYPTOPP_MD5_H
#include "iterhash.h"
NAMESPACE_BEGIN(CryptoPP)
//! <a href="http://www.weidai.com/scan-mirror/md.html#MD5">MD5</a>
/*! 128 Bit Hash */
class MD5 : public 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
+72
View File
@@ -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
+83
View File
@@ -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
+688
View File
@@ -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
+149
View File
@@ -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
+266
View File
@@ -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 &params)
{
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 &params, 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
+370
View File
@@ -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 &params = 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 &params, 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 &params, 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 &params, 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 &params, 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
+182
View File
@@ -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 &parameters, 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
+98
View File
@@ -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 &parameters)
{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 &parameters=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
+143
View File
@@ -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
+107
View File
@@ -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
+25
View File
@@ -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
+112
View File
@@ -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
+172
View File
@@ -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
+162
View File
@@ -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
+13
View File
@@ -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
+126
View File
@@ -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
+70
View File
@@ -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
+579
View File
@@ -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 &parameter, 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
+451
View File
@@ -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 &parameter, 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 &parameter, 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 &parameter) : 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 &parameter) {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 &parameter)
{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
+126
View File
@@ -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
+86
View File
@@ -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
+122
View File
@@ -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
+518
View File
@@ -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 &copy)
{
CopyFrom(copy);
}
void ByteQueue::CopyFrom(const ByteQueue &copy)
{
m_lazyLength = 0;
m_nodeSize = copy.m_nodeSize;
m_head = m_tail = new ByteQueueNode(*copy.m_head);
for (ByteQueueNode *current=copy.m_head->next; current; current=current->next)
{
m_tail->next = new ByteQueueNode(*current);
m_tail = m_tail->next;
}
m_tail->next = NULL;
Put(copy.m_lazyString, copy.m_lazyLength);
}
ByteQueue::~ByteQueue()
{
Destroy();
}
void ByteQueue::Destroy()
{
ByteQueueNode *next;
for (ByteQueueNode *current=m_head; current; current=next)
{
next=current->next;
delete current;
}
}
void ByteQueue::IsolatedInitialize(const NameValuePairs &parameters)
{
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 &parameters)
{
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
+128
View File
@@ -0,0 +1,128 @@
// specification file for an unlimited queue for storing bytes
#ifndef CRYPTOPP_QUEUE_H
#define CRYPTOPP_QUEUE_H
#include "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 &copy);
~ByteQueue();
unsigned long MaxRetrievable() const
{return CurrentSize();}
bool AnyRetrievable() const
{return !IsEmpty();}
void IsolatedInitialize(const NameValuePairs &parameters);
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 &parameters);
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 &copy);
void Destroy();
unsigned int m_nodeSize;
ByteQueueNode *m_head, *m_tail;
const byte *m_lazyString;
unsigned int m_lazyLength;
};
//! use this to make sure LazyPut is finalized in event of exception
class LazyPutter
{
public:
LazyPutter(ByteQueue &bq, const byte *inString, unsigned int size)
: m_bq(bq) {bq.LazyPut(inString, size);}
~LazyPutter()
{try {m_bq.FinalizeLazyPut();} catch(...) {}}
private:
ByteQueue &m_bq;
};
NAMESPACE_END
NAMESPACE_BEGIN(std)
template<> inline void swap(CryptoPP::ByteQueue &a, CryptoPP::ByteQueue &b)
{
a.swap(b);
}
NAMESPACE_END
#endif
+100
View File
@@ -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
+46
View File
@@ -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 &parameters) {}
protected:
void Stir();
private:
SecByteBlock pool, key;
unsigned int addPos, getPos;
};
NAMESPACE_END
#endif
+78
View File
@@ -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
+277
View File
@@ -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
+143
View File
@@ -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
+32
View File
@@ -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
+61
View File
@@ -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
+10
View File
@@ -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
+41
View File
@@ -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
+35
View File
@@ -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
+385
View File
@@ -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
+237
View File
@@ -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 &param)
{
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 &param)
{
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 &param)
{
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 &param)
{
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 &param = 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 &param = 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
+277
View File
@@ -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
+72
View File
@@ -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
+230
View File
@@ -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 &parameters=g_nullNameValuePairs, int propagation=-1) =0;
virtual bool Flush(bool hardFlush, int propagation=-1, bool blocking=true) =0;
private:
void IsolatedInitialize(const NameValuePairs &parameters) {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 &parameters, 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 &parameters=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 &parameters)
{
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 &parameters) =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 &parameters) {}
unsigned int Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking)
{return 0;}
};
NAMESPACE_END
#endif
+215
View File
@@ -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
+188
View File
@@ -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
+288
View File
@@ -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 &params, 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 &params, 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 &params, 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 &registerWord)
{
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 &params, 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 &params = 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 &params, 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 &params, const byte *key, unsigned int length)
{
PolicyInterface &policy = AccessPolicy();
policy.CipherSetKey(params, key, length);
m_leftOver = policy.GetBytesPerIteration();
}
NAMESPACE_END
#endif
+166
View File
@@ -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();
}
+45
View File
@@ -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
+103
View File
@@ -0,0 +1,103 @@
#ifndef CRYPTOPP_WORDS_H
#define CRYPTOPP_WORDS_H
#include "misc.h"
NAMESPACE_BEGIN(CryptoPP)
inline unsigned int CountWords(const word *X, unsigned int N)
{
while (N && X[N-1]==0)
N--;
return N;
}
inline void SetWords(word *r, word a, unsigned int n)
{
for (unsigned int i=0; i<n; i++)
r[i] = a;
}
inline void CopyWords(word *r, const word *a, unsigned int n)
{
for (unsigned int i=0; i<n; i++)
r[i] = a[i];
}
inline void XorWords(word *r, const word *a, const word *b, unsigned int n)
{
for (unsigned int i=0; i<n; i++)
r[i] = a[i] ^ b[i];
}
inline void XorWords(word *r, const word *a, unsigned int n)
{
for (unsigned int i=0; i<n; i++)
r[i] ^= a[i];
}
inline void AndWords(word *r, const word *a, const word *b, unsigned int n)
{
for (unsigned int i=0; i<n; i++)
r[i] = a[i] & b[i];
}
inline void AndWords(word *r, const word *a, unsigned int n)
{
for (unsigned int i=0; i<n; i++)
r[i] &= a[i];
}
inline word ShiftWordsLeftByBits(word *r, unsigned int n, unsigned int shiftBits)
{
assert (shiftBits<WORD_BITS);
word u, carry=0;
if (shiftBits)
for (unsigned int i=0; i<n; i++)
{
u = r[i];
r[i] = (u << shiftBits) | carry;
carry = u >> (WORD_BITS-shiftBits);
}
return carry;
}
inline word ShiftWordsRightByBits(word *r, unsigned int n, unsigned int shiftBits)
{
assert (shiftBits<WORD_BITS);
word u, carry=0;
if (shiftBits)
for (int i=n-1; i>=0; i--)
{
u = r[i];
r[i] = (u >> shiftBits) | carry;
carry = u << (WORD_BITS-shiftBits);
}
return carry;
}
inline void ShiftWordsLeftByWords(word *r, unsigned int n, unsigned int shiftWords)
{
shiftWords = STDMIN(shiftWords, n);
if (shiftWords)
{
for (unsigned int i=n-1; i>=shiftWords; i--)
r[i] = r[i-shiftWords];
SetWords(r, 0, shiftWords);
}
}
inline void ShiftWordsRightByWords(word *r, unsigned int n, unsigned int shiftWords)
{
shiftWords = STDMIN(shiftWords, n);
if (shiftWords)
{
for (unsigned int i=0; i+shiftWords<n; i++)
r[i] = r[i+shiftWords];
SetWords(r+n-shiftWords, 0, shiftWords);
}
}
NAMESPACE_END
#endif
@@ -0,0 +1,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;
}
}