no longer used
This commit is contained in:
@@ -1,67 +0,0 @@
|
||||
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.
|
||||
@@ -1,255 +0,0 @@
|
||||
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
|
||||
cryptopp@weidai.com, 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
|
||||
@@ -1,341 +0,0 @@
|
||||
// algebra.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "global.h"
|
||||
#include "pch.h"
|
||||
#include "algebra.h"
|
||||
#include "integer.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace 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], this->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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,275 +0,0 @@
|
||||
#ifndef CRYPTOPP_ALGEBRA_H
|
||||
#define CRYPTOPP_ALGEBRA_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
namespace 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): AbstractGroup<T>(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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,11 +0,0 @@
|
||||
// algparam.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "global.h"
|
||||
#include "pch.h"
|
||||
#include "algparam.h"
|
||||
|
||||
namespace CryptoPP {
|
||||
|
||||
bool (*AssignIntToInteger)(const std::type_info &valueType, void *pInteger, const void *pInt) = NULL;
|
||||
|
||||
}
|
||||
@@ -1,325 +0,0 @@
|
||||
#ifndef CRYPTOPP_ALGPARAM_H
|
||||
#define CRYPTOPP_ALGPARAM_H
|
||||
|
||||
#include "cryptlib.h"
|
||||
#include "smartptr.h"
|
||||
#include "secblock.h"
|
||||
|
||||
namespace 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 ©)
|
||||
: NameValuePairs( 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)
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,54 +0,0 @@
|
||||
#ifndef CRYPTOPP_ARGNAMES_H
|
||||
#define CRYPTOPP_ARGNAMES_H
|
||||
|
||||
#include "cryptlib.h"
|
||||
|
||||
namespace 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
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,557 +0,0 @@
|
||||
// asn.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "global.h"
|
||||
#include "pch.h"
|
||||
#include "asn.h"
|
||||
|
||||
#include <iomanip>
|
||||
#include <time.h>
|
||||
|
||||
namespace 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 = false;
|
||||
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 = 0;
|
||||
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 = 0;
|
||||
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 = 0;
|
||||
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 = 0;
|
||||
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 = 0;
|
||||
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 = 0;
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,346 +0,0 @@
|
||||
#ifndef CRYPTOPP_ASN_H
|
||||
#define CRYPTOPP_ASN_H
|
||||
|
||||
#include "filters.h"
|
||||
#include "queue.h"
|
||||
#include <vector>
|
||||
|
||||
namespace CryptoPP {
|
||||
|
||||
// these tags and flags are not complete
|
||||
enum ASNTag
|
||||
{
|
||||
BOOLEAN = 0x01,
|
||||
INTEGER = 0x02,
|
||||
BIT_STRING = 0x03,
|
||||
OCTET_STRING = 0x04,
|
||||
TAG_NULL = 0x05,
|
||||
OBJECT_IDENTIFIER = 0x06,
|
||||
OBJECT_DESCRIPTOR = 0x07,
|
||||
EXTERNAL = 0x08,
|
||||
REAL = 0x09,
|
||||
ENUMERATED = 0x0a,
|
||||
UTF8_STRING = 0x0c,
|
||||
SEQUENCE = 0x10,
|
||||
SET = 0x11,
|
||||
NUMERIC_STRING = 0x12,
|
||||
PRINTABLE_STRING = 0x13,
|
||||
T61_STRING = 0x14,
|
||||
VIDEOTEXT_STRING = 0x15,
|
||||
IA5_STRING = 0x16,
|
||||
UTC_TIME = 0x17,
|
||||
GENERALIZED_TIME = 0x18,
|
||||
GRAPHIC_STRING = 0x19,
|
||||
VISIBLE_STRING = 0x1a,
|
||||
GENERAL_STRING = 0x1b
|
||||
};
|
||||
|
||||
enum ASNIdFlag
|
||||
{
|
||||
UNIVERSAL = 0x00,
|
||||
// DATA = 0x01,
|
||||
// HEADER = 0x02,
|
||||
CONSTRUCTED = 0x20,
|
||||
APPLICATION = 0x40,
|
||||
CONTEXT_SPECIFIC = 0x80,
|
||||
PRIVATE = 0xc0
|
||||
};
|
||||
|
||||
inline void BERDecodeError() {throw BERDecodeErr();}
|
||||
|
||||
class UnknownOID : public BERDecodeErr
|
||||
{
|
||||
public:
|
||||
UnknownOID() : BERDecodeErr("BER decode error: unknown object identifier") {}
|
||||
UnknownOID(const char *err) : BERDecodeErr(err) {}
|
||||
};
|
||||
|
||||
// unsigned int DERLengthEncode(unsigned int length, byte *output=0);
|
||||
unsigned int DERLengthEncode(BufferedTransformation &out, unsigned int length);
|
||||
// returns false if indefinite length
|
||||
bool BERLengthDecode(BufferedTransformation &in, unsigned int &length);
|
||||
|
||||
void DEREncodeNull(BufferedTransformation &out);
|
||||
void BERDecodeNull(BufferedTransformation &in);
|
||||
|
||||
unsigned int DEREncodeOctetString(BufferedTransformation &out, const byte *str, unsigned int strLen);
|
||||
unsigned int DEREncodeOctetString(BufferedTransformation &out, const SecByteBlock &str);
|
||||
unsigned int BERDecodeOctetString(BufferedTransformation &in, SecByteBlock &str);
|
||||
unsigned int BERDecodeOctetString(BufferedTransformation &in, BufferedTransformation &str);
|
||||
|
||||
// for UTF8_STRING, PRINTABLE_STRING, and IA5_STRING
|
||||
unsigned int DEREncodeTextString(BufferedTransformation &out, const std::string &str, byte asnTag);
|
||||
unsigned int BERDecodeTextString(BufferedTransformation &in, std::string &str, byte asnTag);
|
||||
|
||||
unsigned int DEREncodeBitString(BufferedTransformation &out, const byte *str, unsigned int strLen, unsigned int unusedBits=0);
|
||||
unsigned int BERDecodeBitString(BufferedTransformation &in, SecByteBlock &str, unsigned int &unusedBits);
|
||||
|
||||
//! Object Identifier
|
||||
class OID
|
||||
{
|
||||
public:
|
||||
OID() {}
|
||||
OID(unsigned long v) : m_values(1, v) {}
|
||||
OID(BufferedTransformation &bt) {BERDecode(bt);}
|
||||
|
||||
inline OID & operator+=(unsigned long rhs) {m_values.push_back(rhs); return *this;}
|
||||
|
||||
void DEREncode(BufferedTransformation &bt) const;
|
||||
void BERDecode(BufferedTransformation &bt);
|
||||
|
||||
// throw BERDecodeErr() if decoded value doesn't equal this OID
|
||||
void BERDecodeAndCheck(BufferedTransformation &bt) const;
|
||||
|
||||
std::vector<unsigned long> m_values;
|
||||
|
||||
private:
|
||||
static void EncodeValue(BufferedTransformation &bt, unsigned long v);
|
||||
static unsigned int DecodeValue(BufferedTransformation &bt, unsigned long &v);
|
||||
};
|
||||
|
||||
class EncodedObjectFilter : public Filter
|
||||
{
|
||||
public:
|
||||
enum Flag {PUT_OBJECTS=1, PUT_MESSANGE_END_AFTER_EACH_OBJECT=2, PUT_MESSANGE_END_AFTER_ALL_OBJECTS=4, PUT_MESSANGE_SERIES_END_AFTER_ALL_OBJECTS=8};
|
||||
EncodedObjectFilter(BufferedTransformation *attachment = NULL, unsigned int nObjects = 1, word32 flags = 0);
|
||||
|
||||
void Put(const byte *inString, unsigned int length);
|
||||
|
||||
unsigned int GetNumberOfCompletedObjects() const {return m_nCurrentObject;}
|
||||
unsigned long GetPositionOfObject(unsigned int i) const {return m_positions[i];}
|
||||
|
||||
private:
|
||||
BufferedTransformation & CurrentTarget();
|
||||
|
||||
word32 m_flags;
|
||||
unsigned int m_nObjects, m_nCurrentObject, m_level;
|
||||
std::vector<unsigned int> m_positions;
|
||||
ByteQueue m_queue;
|
||||
enum State {IDENTIFIER, LENGTH, BODY, TAIL, ALL_DONE} m_state;
|
||||
byte m_id;
|
||||
unsigned int m_lengthRemaining;
|
||||
};
|
||||
|
||||
//! BER General Decoder
|
||||
class BERGeneralDecoder : public Store
|
||||
{
|
||||
public:
|
||||
explicit BERGeneralDecoder(BufferedTransformation &inQueue, byte asnTag);
|
||||
explicit BERGeneralDecoder(BERGeneralDecoder &inQueue, byte asnTag);
|
||||
~BERGeneralDecoder();
|
||||
|
||||
bool IsDefiniteLength() const {return m_definiteLength;}
|
||||
unsigned int RemainingLength() const {assert(m_definiteLength); return m_length;}
|
||||
bool EndReached() const;
|
||||
byte PeekByte() const;
|
||||
void CheckByte(byte b);
|
||||
|
||||
unsigned int TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel=NULL_CHANNEL, bool blocking=true);
|
||||
unsigned int CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end=ULONG_MAX, const std::string &channel=NULL_CHANNEL, bool blocking=true) const;
|
||||
|
||||
// call this to denote end of sequence
|
||||
void MessageEnd();
|
||||
|
||||
protected:
|
||||
BufferedTransformation &m_inQueue;
|
||||
bool m_finished, m_definiteLength;
|
||||
unsigned int m_length;
|
||||
|
||||
private:
|
||||
void StoreInitialize(const NameValuePairs ¶meters) {assert(false);}
|
||||
unsigned int ReduceLength(unsigned int delta);
|
||||
};
|
||||
|
||||
//! DER General Encoder
|
||||
class DERGeneralEncoder : public ByteQueue
|
||||
{
|
||||
public:
|
||||
explicit DERGeneralEncoder(BufferedTransformation &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED);
|
||||
explicit DERGeneralEncoder(DERGeneralEncoder &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED);
|
||||
~DERGeneralEncoder();
|
||||
|
||||
// call this to denote end of sequence
|
||||
void MessageEnd();
|
||||
|
||||
private:
|
||||
BufferedTransformation &m_outQueue;
|
||||
bool m_finished;
|
||||
|
||||
byte m_asnTag;
|
||||
};
|
||||
|
||||
//! BER Sequence Decoder
|
||||
class BERSequenceDecoder : public BERGeneralDecoder
|
||||
{
|
||||
public:
|
||||
explicit BERSequenceDecoder(BufferedTransformation &inQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
|
||||
: BERGeneralDecoder(inQueue, asnTag) {}
|
||||
explicit BERSequenceDecoder(BERSequenceDecoder &inQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
|
||||
: BERGeneralDecoder(inQueue, asnTag) {}
|
||||
};
|
||||
|
||||
//! DER Sequence Encoder
|
||||
class DERSequenceEncoder : public DERGeneralEncoder
|
||||
{
|
||||
public:
|
||||
explicit DERSequenceEncoder(BufferedTransformation &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
|
||||
: DERGeneralEncoder(outQueue, asnTag) {}
|
||||
explicit DERSequenceEncoder(DERSequenceEncoder &outQueue, byte asnTag = SEQUENCE | CONSTRUCTED)
|
||||
: DERGeneralEncoder(outQueue, asnTag) {}
|
||||
};
|
||||
|
||||
//! BER Set Decoder
|
||||
class BERSetDecoder : public BERGeneralDecoder
|
||||
{
|
||||
public:
|
||||
explicit BERSetDecoder(BufferedTransformation &inQueue, byte asnTag = SET | CONSTRUCTED)
|
||||
: BERGeneralDecoder(inQueue, asnTag) {}
|
||||
explicit BERSetDecoder(BERSetDecoder &inQueue, byte asnTag = SET | CONSTRUCTED)
|
||||
: BERGeneralDecoder(inQueue, asnTag) {}
|
||||
};
|
||||
|
||||
//! DER Set Encoder
|
||||
class DERSetEncoder : public DERGeneralEncoder
|
||||
{
|
||||
public:
|
||||
explicit DERSetEncoder(BufferedTransformation &outQueue, byte asnTag = SET | CONSTRUCTED)
|
||||
: DERGeneralEncoder(outQueue, asnTag) {}
|
||||
explicit DERSetEncoder(DERSetEncoder &outQueue, byte asnTag = SET | CONSTRUCTED)
|
||||
: DERGeneralEncoder(outQueue, asnTag) {}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class ASNOptional : public member_ptr<T>
|
||||
{
|
||||
public:
|
||||
void BERDecode(BERSequenceDecoder &seqDecoder, byte tag, byte mask = ~CONSTRUCTED)
|
||||
{
|
||||
byte b;
|
||||
if (seqDecoder.Peek(b) && (b & mask) == tag)
|
||||
reset(new T(seqDecoder));
|
||||
}
|
||||
void DEREncode(BufferedTransformation &out)
|
||||
{
|
||||
if (this->get() != NULL)
|
||||
this->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 = 0;
|
||||
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
|
||||
@@ -1,257 +0,0 @@
|
||||
#ifndef CRYPTOPP_CONFIG_H
|
||||
#define CRYPTOPP_CONFIG_H
|
||||
|
||||
// ***************** Important Settings ********************
|
||||
|
||||
#include "global.h"
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning (disable : 4244) // conversion ... possible loss of data
|
||||
#pragma warning (disable : 4516) // access-declarations are deprecated
|
||||
#pragma warning (disable : 4511) // copy constructor could not be generated
|
||||
#pragma warning (disable : 4189) // local variable is initialized but not referenced
|
||||
#endif
|
||||
|
||||
// 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
|
||||
#ifdef _XBOX
|
||||
# define NO_OS_DEPENDENCE
|
||||
#endif
|
||||
|
||||
// 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 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(__ppc__) || defined(__ppc64__) || 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
|
||||
|
||||
}
|
||||
|
||||
// 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__) || defined(__NetBSD__)
|
||||
#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
|
||||
@@ -1,652 +0,0 @@
|
||||
// cryptlib.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "global.h"
|
||||
#include "pch.h"
|
||||
#include "cryptlib.h"
|
||||
#include "misc.h"
|
||||
#include "filters.h"
|
||||
#include "algparam.h"
|
||||
#include "argnames.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace CryptoPP {
|
||||
|
||||
//CRYPTOPP_COMPILE_ASSERT(sizeof(byte) == 1);
|
||||
//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)
|
||||
{
|
||||
}
|
||||
|
||||
void SimpleKeyingInterface::SetKeyWithRounds(const byte *key, unsigned int length, int rounds)
|
||||
{
|
||||
SetKey(key, length, MakeParameters(Name::Rounds(), rounds));
|
||||
}
|
||||
|
||||
void SimpleKeyingInterface::SetKeyWithIV(const byte *key, unsigned int length, const byte *iv)
|
||||
{
|
||||
SetKey(key, length, MakeParameters(Name::IV(), iv));
|
||||
}
|
||||
|
||||
void SimpleKeyingInterface::ThrowIfInvalidKeyLength(const Algorithm &algorithm, unsigned int length)
|
||||
{
|
||||
if (!IsValidKeyLength(length))
|
||||
throw InvalidKeyLength(algorithm.AlgorithmName(), length);
|
||||
}
|
||||
|
||||
void BlockTransformation::ProcessAndXorMultipleBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, unsigned int numberOfBlocks) const
|
||||
{
|
||||
unsigned int blockSize = BlockSize();
|
||||
while (numberOfBlocks--)
|
||||
{
|
||||
ProcessAndXorBlock(inBlocks, xorBlocks, outBlocks);
|
||||
inBlocks += blockSize;
|
||||
outBlocks += blockSize;
|
||||
if (xorBlocks)
|
||||
xorBlocks += blockSize;
|
||||
}
|
||||
}
|
||||
|
||||
void StreamTransformation::ProcessLastBlock(byte *outString, const byte *inString, unsigned int length)
|
||||
{
|
||||
assert(MinLastBlockSize() == 0); // this function should be overriden otherwise
|
||||
|
||||
if (length == MandatoryBlockSize())
|
||||
ProcessData(outString, inString, length);
|
||||
else if (length != 0)
|
||||
throw NotImplemented("StreamTransformation: this object does't support a special last block");
|
||||
}
|
||||
|
||||
unsigned int RandomNumberGenerator::GenerateBit()
|
||||
{
|
||||
return Parity(GenerateByte());
|
||||
}
|
||||
|
||||
void RandomNumberGenerator::GenerateBlock(byte *output, unsigned int size)
|
||||
{
|
||||
while (size--)
|
||||
*output++ = GenerateByte();
|
||||
}
|
||||
|
||||
word32 RandomNumberGenerator::GenerateWord32(word32 min, word32 max)
|
||||
{
|
||||
word32 range = max-min;
|
||||
const int maxBytes = BytePrecision(range);
|
||||
const int maxBits = BitPrecision(range);
|
||||
|
||||
word32 value;
|
||||
|
||||
do
|
||||
{
|
||||
value = 0;
|
||||
for (int i=0; i<maxBytes; i++)
|
||||
value = (value << 8) | GenerateByte();
|
||||
|
||||
value = Crop(value, maxBits);
|
||||
} while (value > range);
|
||||
|
||||
return value+min;
|
||||
}
|
||||
|
||||
void RandomNumberGenerator::DiscardBytes(unsigned int n)
|
||||
{
|
||||
while (n--)
|
||||
GenerateByte();
|
||||
}
|
||||
|
||||
RandomNumberGenerator & NullRNG()
|
||||
{
|
||||
class NullRNG : public RandomNumberGenerator
|
||||
{
|
||||
public:
|
||||
std::string AlgorithmName() const {return "NullRNG";}
|
||||
byte GenerateByte() {throw NotImplemented("NullRNG: NullRNG should only be passed to functions that don't need to generate random bytes");}
|
||||
};
|
||||
|
||||
static NullRNG s_nullRNG;
|
||||
return s_nullRNG;
|
||||
}
|
||||
|
||||
bool HashTransformation::TruncatedVerify(const byte *digestIn, unsigned int digestLength)
|
||||
{
|
||||
ThrowIfInvalidTruncatedSize(digestLength);
|
||||
SecByteBlock digest(digestLength);
|
||||
TruncatedFinal(digest, digestLength);
|
||||
return memcmp(digest, digestIn, digestLength) == 0;
|
||||
}
|
||||
|
||||
void HashTransformation::ThrowIfInvalidTruncatedSize(unsigned int size) const
|
||||
{
|
||||
if (size > DigestSize())
|
||||
throw InvalidArgument("HashTransformation: can't truncate a " + IntToString(DigestSize()) + " byte digest to " + IntToString(size) + " bytes");
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::GetMaxWaitObjectCount() const
|
||||
{
|
||||
const BufferedTransformation *t = AttachedTransformation();
|
||||
return t ? t->GetMaxWaitObjectCount() : 0;
|
||||
}
|
||||
|
||||
void BufferedTransformation::GetWaitObjects(WaitObjectContainer &container)
|
||||
{
|
||||
BufferedTransformation *t = AttachedTransformation();
|
||||
if (t)
|
||||
t->GetWaitObjects(container);
|
||||
}
|
||||
|
||||
void BufferedTransformation::Initialize(const NameValuePairs ¶meters, int propagation)
|
||||
{
|
||||
assert(!AttachedTransformation());
|
||||
IsolatedInitialize(parameters);
|
||||
}
|
||||
|
||||
bool BufferedTransformation::Flush(bool hardFlush, int propagation, bool blocking)
|
||||
{
|
||||
assert(!AttachedTransformation());
|
||||
return IsolatedFlush(hardFlush, blocking);
|
||||
}
|
||||
|
||||
bool BufferedTransformation::MessageSeriesEnd(int propagation, bool blocking)
|
||||
{
|
||||
assert(!AttachedTransformation());
|
||||
return IsolatedMessageSeriesEnd(blocking);
|
||||
}
|
||||
|
||||
byte * BufferedTransformation::ChannelCreatePutSpace(const std::string &channel, unsigned int &size)
|
||||
{
|
||||
if (channel.empty())
|
||||
return CreatePutSpace(size);
|
||||
else
|
||||
throw NoChannelSupport();
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::ChannelPut2(const std::string &channel, const byte *begin, unsigned int length, int messageEnd, bool blocking)
|
||||
{
|
||||
if (channel.empty())
|
||||
return Put2(begin, length, messageEnd, blocking);
|
||||
else
|
||||
throw NoChannelSupport();
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::ChannelPutModifiable2(const std::string &channel, byte *begin, unsigned int length, int messageEnd, bool blocking)
|
||||
{
|
||||
if (channel.empty())
|
||||
return PutModifiable2(begin, length, messageEnd, blocking);
|
||||
else
|
||||
return ChannelPut2(channel, begin, length, messageEnd, blocking);
|
||||
}
|
||||
|
||||
void BufferedTransformation::ChannelInitialize(const std::string &channel, const NameValuePairs ¶meters, int propagation)
|
||||
{
|
||||
if (channel.empty())
|
||||
Initialize(parameters, propagation);
|
||||
else
|
||||
throw NoChannelSupport();
|
||||
}
|
||||
|
||||
bool BufferedTransformation::ChannelFlush(const std::string &channel, bool completeFlush, int propagation, bool blocking)
|
||||
{
|
||||
if (channel.empty())
|
||||
return Flush(completeFlush, propagation, blocking);
|
||||
else
|
||||
throw NoChannelSupport();
|
||||
}
|
||||
|
||||
bool BufferedTransformation::ChannelMessageSeriesEnd(const std::string &channel, int propagation, bool blocking)
|
||||
{
|
||||
if (channel.empty())
|
||||
return MessageSeriesEnd(propagation, blocking);
|
||||
else
|
||||
throw NoChannelSupport();
|
||||
}
|
||||
|
||||
unsigned long BufferedTransformation::MaxRetrievable() const
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->MaxRetrievable();
|
||||
else
|
||||
return CopyTo(TheBitBucket());
|
||||
}
|
||||
|
||||
bool BufferedTransformation::AnyRetrievable() const
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->AnyRetrievable();
|
||||
else
|
||||
{
|
||||
byte b;
|
||||
return Peek(b) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::Get(byte &outByte)
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->Get(outByte);
|
||||
else
|
||||
return Get(&outByte, 1);
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::Get(byte *outString, unsigned int getMax)
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->Get(outString, getMax);
|
||||
else
|
||||
{
|
||||
ArraySink arraySink(outString, getMax);
|
||||
return TransferTo(arraySink, getMax);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::Peek(byte &outByte) const
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->Peek(outByte);
|
||||
else
|
||||
return Peek(&outByte, 1);
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::Peek(byte *outString, unsigned int peekMax) const
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->Peek(outString, peekMax);
|
||||
else
|
||||
{
|
||||
ArraySink arraySink(outString, peekMax);
|
||||
return CopyTo(arraySink, peekMax);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long BufferedTransformation::Skip(unsigned long skipMax)
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->Skip(skipMax);
|
||||
else
|
||||
return TransferTo(TheBitBucket(), skipMax);
|
||||
}
|
||||
|
||||
unsigned long BufferedTransformation::TotalBytesRetrievable() const
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->TotalBytesRetrievable();
|
||||
else
|
||||
return MaxRetrievable();
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::NumberOfMessages() const
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->NumberOfMessages();
|
||||
else
|
||||
return CopyMessagesTo(TheBitBucket());
|
||||
}
|
||||
|
||||
bool BufferedTransformation::AnyMessages() const
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->AnyMessages();
|
||||
else
|
||||
return NumberOfMessages() != 0;
|
||||
}
|
||||
|
||||
bool BufferedTransformation::GetNextMessage()
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->GetNextMessage();
|
||||
else
|
||||
{
|
||||
assert(!AnyMessages());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::SkipMessages(unsigned int count)
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->SkipMessages(count);
|
||||
else
|
||||
return TransferMessagesTo(TheBitBucket(), count);
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::TransferMessagesTo2(BufferedTransformation &target, unsigned int &messageCount, const std::string &channel, bool blocking)
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->TransferMessagesTo2(target, messageCount, channel, blocking);
|
||||
else
|
||||
{
|
||||
unsigned int maxMessages = messageCount;
|
||||
for (messageCount=0; messageCount < maxMessages && AnyMessages(); messageCount++)
|
||||
{
|
||||
unsigned int blockedBytes;
|
||||
unsigned long transferedBytes;
|
||||
|
||||
while (AnyRetrievable())
|
||||
{
|
||||
transferedBytes = ULONG_MAX;
|
||||
blockedBytes = TransferTo2(target, transferedBytes, channel, blocking);
|
||||
if (blockedBytes > 0)
|
||||
return blockedBytes;
|
||||
}
|
||||
|
||||
if (target.ChannelMessageEnd(channel, GetAutoSignalPropagation(), blocking))
|
||||
return 1;
|
||||
|
||||
bool result = GetNextMessage();
|
||||
assert(result);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::CopyMessagesTo(BufferedTransformation &target, unsigned int count, const std::string &channel) const
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->CopyMessagesTo(target, count, channel);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void BufferedTransformation::SkipAll()
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
AttachedTransformation()->SkipAll();
|
||||
else
|
||||
{
|
||||
while (SkipMessages()) {}
|
||||
while (Skip()) {}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::TransferAllTo2(BufferedTransformation &target, const std::string &channel, bool blocking)
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
return AttachedTransformation()->TransferAllTo2(target, channel, blocking);
|
||||
else
|
||||
{
|
||||
assert(!NumberOfMessageSeries());
|
||||
|
||||
unsigned int messageCount;
|
||||
do
|
||||
{
|
||||
messageCount = UINT_MAX;
|
||||
unsigned int blockedBytes = TransferMessagesTo2(target, messageCount, channel, blocking);
|
||||
if (blockedBytes)
|
||||
return blockedBytes;
|
||||
}
|
||||
while (messageCount != 0);
|
||||
|
||||
unsigned long byteCount;
|
||||
do
|
||||
{
|
||||
byteCount = ULONG_MAX;
|
||||
unsigned int blockedBytes = TransferTo2(target, byteCount, channel, blocking);
|
||||
if (blockedBytes)
|
||||
return blockedBytes;
|
||||
}
|
||||
while (byteCount != 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void BufferedTransformation::CopyAllTo(BufferedTransformation &target, const std::string &channel) const
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
AttachedTransformation()->CopyAllTo(target, channel);
|
||||
else
|
||||
{
|
||||
assert(!NumberOfMessageSeries());
|
||||
while (CopyMessagesTo(target, UINT_MAX, channel)) {}
|
||||
}
|
||||
}
|
||||
|
||||
void BufferedTransformation::SetRetrievalChannel(const std::string &channel)
|
||||
{
|
||||
if (AttachedTransformation())
|
||||
AttachedTransformation()->SetRetrievalChannel(channel);
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::ChannelPutWord16(const std::string &channel, word16 value, ByteOrder order, bool blocking)
|
||||
{
|
||||
FixedSizeSecBlock<byte, 2> buf;
|
||||
PutWord(false, order, buf, value);
|
||||
return ChannelPut(channel, buf, 2, blocking);
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::ChannelPutWord32(const std::string &channel, word32 value, ByteOrder order, bool blocking)
|
||||
{
|
||||
FixedSizeSecBlock<byte, 4> buf;
|
||||
PutWord(false, order, buf, value);
|
||||
return ChannelPut(channel, buf, 4, blocking);
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::PutWord16(word16 value, ByteOrder order, bool blocking)
|
||||
{
|
||||
return ChannelPutWord16(NULL_CHANNEL, value, order, blocking);
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::PutWord32(word32 value, ByteOrder order, bool blocking)
|
||||
{
|
||||
return ChannelPutWord32(NULL_CHANNEL, value, order, blocking);
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::PeekWord16(word16 &value, ByteOrder order)
|
||||
{
|
||||
byte buf[2] = {0, 0};
|
||||
unsigned int len = Peek(buf, 2);
|
||||
|
||||
if (order)
|
||||
value = (buf[0] << 8) | buf[1];
|
||||
else
|
||||
value = (buf[1] << 8) | buf[0];
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::PeekWord32(word32 &value, ByteOrder order)
|
||||
{
|
||||
byte buf[4] = {0, 0, 0, 0};
|
||||
unsigned int len = Peek(buf, 4);
|
||||
|
||||
if (order)
|
||||
value = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf [3];
|
||||
else
|
||||
value = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf [0];
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::GetWord16(word16 &value, ByteOrder order)
|
||||
{
|
||||
return Skip(PeekWord16(value, order));
|
||||
}
|
||||
|
||||
unsigned int BufferedTransformation::GetWord32(word32 &value, ByteOrder order)
|
||||
{
|
||||
return Skip(PeekWord32(value, order));
|
||||
}
|
||||
|
||||
void BufferedTransformation::Attach(BufferedTransformation *newOut)
|
||||
{
|
||||
if (AttachedTransformation() && AttachedTransformation()->Attachable())
|
||||
AttachedTransformation()->Attach(newOut);
|
||||
else
|
||||
Detach(newOut);
|
||||
}
|
||||
|
||||
void GeneratableCryptoMaterial::GenerateRandomWithKeySize(RandomNumberGenerator &rng, unsigned int keySize)
|
||||
{
|
||||
GenerateRandom(rng, MakeParameters("KeySize", (int)keySize));
|
||||
}
|
||||
|
||||
BufferedTransformation * PK_Encryptor::CreateEncryptionFilter(RandomNumberGenerator &rng, BufferedTransformation *attachment) const
|
||||
{
|
||||
struct EncryptionFilter : public Unflushable<FilterWithInputQueue>
|
||||
{
|
||||
// VC60 complains if this function is missing
|
||||
EncryptionFilter(const EncryptionFilter &x) : Unflushable<FilterWithInputQueue>(NULL), m_rng(x.m_rng), m_encryptor(x.m_encryptor) {}
|
||||
|
||||
EncryptionFilter(RandomNumberGenerator &rng, const PK_Encryptor &encryptor, BufferedTransformation *attachment)
|
||||
: Unflushable<FilterWithInputQueue>(attachment), m_rng(rng), m_encryptor(encryptor)
|
||||
{
|
||||
}
|
||||
|
||||
bool IsolatedMessageEnd(bool blocking)
|
||||
{
|
||||
switch (m_continueAt)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
unsigned int plaintextLength = m_inQueue.CurrentSize();
|
||||
m_ciphertextLength = m_encryptor.CiphertextLength(plaintextLength);
|
||||
|
||||
SecByteBlock plaintext(plaintextLength);
|
||||
m_inQueue.Get(plaintext, plaintextLength);
|
||||
m_ciphertext.resize(m_ciphertextLength);
|
||||
m_encryptor.Encrypt(m_rng, plaintext, plaintextLength, m_ciphertext);
|
||||
}
|
||||
|
||||
case 1:
|
||||
if (!Output(1, m_ciphertext, m_ciphertextLength, 0, blocking))
|
||||
return false;
|
||||
};
|
||||
return true;
|
||||
}
|
||||
|
||||
RandomNumberGenerator &m_rng;
|
||||
const PK_Encryptor &m_encryptor;
|
||||
unsigned int m_ciphertextLength;
|
||||
SecByteBlock m_ciphertext;
|
||||
};
|
||||
|
||||
return new EncryptionFilter(rng, *this, attachment);
|
||||
}
|
||||
|
||||
BufferedTransformation * PK_Decryptor::CreateDecryptionFilter(RandomNumberGenerator &rng, BufferedTransformation *attachment) const
|
||||
{
|
||||
struct DecryptionFilter : public Unflushable<FilterWithInputQueue>
|
||||
{
|
||||
// VC60 complains if this function is missing
|
||||
DecryptionFilter(const DecryptionFilter &x) : Unflushable<FilterWithInputQueue>(NULL), m_rng(x.m_rng), m_decryptor(x.m_decryptor) {}
|
||||
|
||||
DecryptionFilter(RandomNumberGenerator &rng, const PK_Decryptor &decryptor, BufferedTransformation *attachment)
|
||||
: Unflushable<FilterWithInputQueue>(attachment), m_rng(rng), m_decryptor(decryptor)
|
||||
{
|
||||
}
|
||||
|
||||
bool IsolatedMessageEnd(bool blocking)
|
||||
{
|
||||
switch (m_continueAt)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
unsigned int ciphertextLength = m_inQueue.CurrentSize();
|
||||
unsigned int maxPlaintextLength = m_decryptor.MaxPlaintextLength(ciphertextLength);
|
||||
|
||||
SecByteBlock ciphertext(ciphertextLength);
|
||||
m_inQueue.Get(ciphertext, ciphertextLength);
|
||||
m_plaintext.resize(maxPlaintextLength);
|
||||
m_result = m_decryptor.Decrypt(m_rng, ciphertext, ciphertextLength, m_plaintext);
|
||||
if (!m_result.isValidCoding)
|
||||
throw InvalidCiphertext(m_decryptor.AlgorithmName() + ": invalid ciphertext");
|
||||
}
|
||||
|
||||
case 1:
|
||||
if (!Output(1, m_plaintext, m_result.messageLength, 0, blocking))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
RandomNumberGenerator &m_rng;
|
||||
const PK_Decryptor &m_decryptor;
|
||||
SecByteBlock m_plaintext;
|
||||
DecodingResult m_result;
|
||||
};
|
||||
|
||||
return new DecryptionFilter(rng, *this, attachment);
|
||||
}
|
||||
|
||||
unsigned int PK_FixedLengthCryptoSystem::MaxPlaintextLength(unsigned int cipherTextLength) const
|
||||
{
|
||||
if (cipherTextLength == FixedCiphertextLength())
|
||||
return FixedMaxPlaintextLength();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int PK_FixedLengthCryptoSystem::CiphertextLength(unsigned int plainTextLength) const
|
||||
{
|
||||
if (plainTextLength <= FixedMaxPlaintextLength())
|
||||
return FixedCiphertextLength();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,188 +0,0 @@
|
||||
// files.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "global.h"
|
||||
#include "pch.h"
|
||||
#include "files.h"
|
||||
|
||||
namespace CryptoPP {
|
||||
|
||||
using namespace std;
|
||||
|
||||
void Files_TestInstantiations()
|
||||
{
|
||||
FileStore f0;
|
||||
FileSource f1;
|
||||
FileSink f2;
|
||||
}
|
||||
|
||||
void FileStore::StoreInitialize(const NameValuePairs ¶meters)
|
||||
{
|
||||
const char *fileName;
|
||||
if (parameters.GetValue("InputFileName", fileName))
|
||||
{
|
||||
ios::openmode binary = parameters.GetValueWithDefault("InputBinaryMode", true) ? ios::binary : ios::openmode(0);
|
||||
m_file.open(fileName, ios::in | binary);
|
||||
if (!m_file)
|
||||
throw OpenErr(fileName);
|
||||
m_stream = &m_file;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_stream = NULL;
|
||||
parameters.GetValue("InputStreamPointer", m_stream);
|
||||
}
|
||||
m_waiting = false;
|
||||
}
|
||||
|
||||
unsigned long FileStore::MaxRetrievable() const
|
||||
{
|
||||
if (!m_stream)
|
||||
return 0;
|
||||
|
||||
streampos current = m_stream->tellg();
|
||||
streampos end = m_stream->seekg(0, ios::end).tellg();
|
||||
m_stream->seekg(current);
|
||||
return end-current;
|
||||
}
|
||||
|
||||
unsigned int FileStore::TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel, bool blocking)
|
||||
{
|
||||
if (!m_stream)
|
||||
{
|
||||
transferBytes = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned long size=transferBytes;
|
||||
transferBytes = 0;
|
||||
|
||||
if (m_waiting)
|
||||
goto output;
|
||||
|
||||
while (size && m_stream->good())
|
||||
{
|
||||
{
|
||||
unsigned int spaceSize = 1024;
|
||||
m_space = HelpCreatePutSpace(target, channel, 1, (unsigned int)STDMIN(size, (unsigned long)UINT_MAX), spaceSize);
|
||||
|
||||
m_stream->read((char *)m_space, STDMIN(size, (unsigned long)spaceSize));
|
||||
}
|
||||
m_len = m_stream->gcount();
|
||||
unsigned int blockedBytes;
|
||||
output:
|
||||
blockedBytes = target.ChannelPutModifiable2(channel, m_space, m_len, 0, blocking);
|
||||
m_waiting = blockedBytes > 0;
|
||||
if (m_waiting)
|
||||
return blockedBytes;
|
||||
size -= m_len;
|
||||
transferBytes += m_len;
|
||||
}
|
||||
|
||||
if (!m_stream->good() && !m_stream->eof())
|
||||
throw ReadErr();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int FileStore::CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end, const std::string &channel, bool blocking) const
|
||||
{
|
||||
if (!m_stream)
|
||||
return 0;
|
||||
|
||||
if (begin == 0 && end == 1)
|
||||
{
|
||||
int result = m_stream->peek();
|
||||
if (result == EOF) // GCC workaround: 2.95.2 doesn't have char_traits<char>::eof()
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
unsigned int blockedBytes = target.ChannelPut(channel, byte(result), blocking);
|
||||
begin += 1-blockedBytes;
|
||||
return blockedBytes;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: figure out what happens on cin
|
||||
streampos current = m_stream->tellg();
|
||||
streampos endPosition = m_stream->seekg(0, ios::end).tellg();
|
||||
streampos newPosition = current + (streamoff)begin;
|
||||
|
||||
// if (newPosition >= endPosition)
|
||||
if (std::streamoff(newPosition) >= std::streamoff(endPosition))
|
||||
{
|
||||
m_stream->seekg(current);
|
||||
return 0; // don't try to seek beyond the end of file
|
||||
}
|
||||
m_stream->seekg(newPosition);
|
||||
|
||||
try
|
||||
{
|
||||
assert(!m_waiting);
|
||||
unsigned long copyMax = end-begin;
|
||||
unsigned int blockedBytes = const_cast<FileStore *>(this)->TransferTo2(target, copyMax, channel, blocking);
|
||||
begin += copyMax;
|
||||
if (blockedBytes)
|
||||
{
|
||||
const_cast<FileStore *>(this)->m_waiting = false;
|
||||
return blockedBytes;
|
||||
}
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
m_stream->clear();
|
||||
m_stream->seekg(current);
|
||||
throw;
|
||||
}
|
||||
m_stream->clear();
|
||||
m_stream->seekg(current);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FileSink::IsolatedInitialize(const NameValuePairs ¶meters)
|
||||
{
|
||||
const char *fileName;
|
||||
if (parameters.GetValue("OutputFileName", fileName))
|
||||
{
|
||||
ios::openmode binary = parameters.GetValueWithDefault("OutputBinaryMode", true) ? ios::binary : ios::openmode(0);
|
||||
m_file.open(fileName, ios::out | ios::trunc | binary);
|
||||
if (!m_file)
|
||||
throw OpenErr(fileName);
|
||||
m_stream = &m_file;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_stream = NULL;
|
||||
parameters.GetValue("OutputStreamPointer", m_stream);
|
||||
}
|
||||
}
|
||||
|
||||
bool FileSink::IsolatedFlush(bool hardFlush, bool blocking)
|
||||
{
|
||||
if (!m_stream)
|
||||
throw Err("FileSink: output stream not opened");
|
||||
|
||||
m_stream->flush();
|
||||
if (!m_stream->good())
|
||||
throw WriteErr();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int FileSink::Put2(const byte *inString, unsigned int length, int messageEnd, bool blocking)
|
||||
{
|
||||
if (!m_stream)
|
||||
throw Err("FileSink: output stream not opened");
|
||||
|
||||
m_stream->write((const char *)inString, length);
|
||||
|
||||
if (messageEnd)
|
||||
m_stream->flush();
|
||||
|
||||
if (!m_stream->good())
|
||||
throw WriteErr();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
#ifndef CRYPTOPP_FILES_H
|
||||
#define CRYPTOPP_FILES_H
|
||||
|
||||
#include "cryptlib.h"
|
||||
#include "filters.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
namespace CryptoPP {
|
||||
|
||||
//! .
|
||||
class FileStore : public Store, private FilterPutSpaceHelper
|
||||
{
|
||||
public:
|
||||
class Err : public Exception
|
||||
{
|
||||
public:
|
||||
Err(const std::string &s) : Exception(IO_ERROR, s) {}
|
||||
};
|
||||
class OpenErr : public Err {public: OpenErr(const std::string &filename) : Err("FileStore: error opening file for reading: " + filename) {}};
|
||||
class ReadErr : public Err {public: ReadErr() : Err("FileStore: error reading file") {}};
|
||||
|
||||
FileStore() : m_stream(NULL) {}
|
||||
FileStore(std::istream &in)
|
||||
{StoreInitialize(MakeParameters("InputStreamPointer", &in));}
|
||||
FileStore(const char *filename)
|
||||
{StoreInitialize(MakeParameters("InputFileName", filename));}
|
||||
|
||||
std::istream* GetStream() {return m_stream;}
|
||||
|
||||
unsigned long MaxRetrievable() const;
|
||||
unsigned int TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel=NULL_CHANNEL, bool blocking=true);
|
||||
unsigned int CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end=ULONG_MAX, const std::string &channel=NULL_CHANNEL, bool blocking=true) const;
|
||||
|
||||
private:
|
||||
void StoreInitialize(const NameValuePairs ¶meters);
|
||||
|
||||
std::ifstream m_file;
|
||||
std::istream *m_stream;
|
||||
byte *m_space;
|
||||
unsigned int m_len;
|
||||
bool m_waiting;
|
||||
};
|
||||
|
||||
//! .
|
||||
class FileSource : public SourceTemplate<FileStore>
|
||||
{
|
||||
public:
|
||||
typedef FileStore::Err Err;
|
||||
typedef FileStore::OpenErr OpenErr;
|
||||
typedef FileStore::ReadErr ReadErr;
|
||||
|
||||
FileSource(BufferedTransformation *attachment = NULL)
|
||||
: SourceTemplate<FileStore>(attachment) {}
|
||||
FileSource(std::istream &in, bool pumpAll, BufferedTransformation *attachment = NULL)
|
||||
: SourceTemplate<FileStore>(attachment) {SourceInitialize(pumpAll, MakeParameters("InputStreamPointer", &in));}
|
||||
FileSource(const char *filename, bool pumpAll, BufferedTransformation *attachment = NULL, bool binary=true)
|
||||
: SourceTemplate<FileStore>(attachment) {SourceInitialize(pumpAll, MakeParameters("InputFileName", filename)("InputBinaryMode", binary));}
|
||||
|
||||
std::istream* GetStream() {return m_store.GetStream();}
|
||||
};
|
||||
|
||||
//! .
|
||||
class FileSink : public Sink
|
||||
{
|
||||
public:
|
||||
class Err : public Exception
|
||||
{
|
||||
public:
|
||||
Err(const std::string &s) : Exception(IO_ERROR, s) {}
|
||||
};
|
||||
class OpenErr : public Err {public: OpenErr(const std::string &filename) : Err("FileSink: error opening file for writing: " + filename) {}};
|
||||
class WriteErr : public Err {public: WriteErr() : Err("FileSink: error writing file") {}};
|
||||
|
||||
FileSink() : m_stream(NULL) {}
|
||||
FileSink(std::ostream &out)
|
||||
{IsolatedInitialize(MakeParameters("OutputStreamPointer", &out));}
|
||||
FileSink(const char *filename, bool binary=true)
|
||||
{IsolatedInitialize(MakeParameters("OutputFileName", filename)("OutputBinaryMode", binary));}
|
||||
|
||||
std::ostream* GetStream() {return m_stream;}
|
||||
|
||||
void IsolatedInitialize(const NameValuePairs ¶meters);
|
||||
unsigned int Put2(const byte *inString, unsigned int length, int messageEnd, bool blocking);
|
||||
bool IsolatedFlush(bool hardFlush, bool blocking);
|
||||
|
||||
private:
|
||||
std::ofstream m_file;
|
||||
std::ostream *m_stream;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,609 +0,0 @@
|
||||
// filters.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "global.h"
|
||||
#include "pch.h"
|
||||
#include "filters.h"
|
||||
#include "mqueue.h"
|
||||
#include "fltrimpl.h"
|
||||
#include "argnames.h"
|
||||
#include <functional>
|
||||
|
||||
namespace CryptoPP {
|
||||
|
||||
Filter::Filter(BufferedTransformation *attachment)
|
||||
: m_attachment(attachment), m_continueAt(0)
|
||||
{
|
||||
}
|
||||
|
||||
BufferedTransformation * Filter::NewDefaultAttachment() const
|
||||
{
|
||||
return new MessageQueue;
|
||||
}
|
||||
|
||||
BufferedTransformation * Filter::AttachedTransformation()
|
||||
{
|
||||
if (m_attachment.get() == NULL)
|
||||
m_attachment.reset(NewDefaultAttachment());
|
||||
return m_attachment.get();
|
||||
}
|
||||
|
||||
const BufferedTransformation *Filter::AttachedTransformation() const
|
||||
{
|
||||
if (m_attachment.get() == NULL)
|
||||
const_cast<Filter *>(this)->m_attachment.reset(NewDefaultAttachment());
|
||||
return m_attachment.get();
|
||||
}
|
||||
|
||||
void Filter::Detach(BufferedTransformation *newOut)
|
||||
{
|
||||
m_attachment.reset(newOut);
|
||||
NotifyAttachmentChange();
|
||||
}
|
||||
|
||||
void Filter::Insert(Filter *filter)
|
||||
{
|
||||
filter->m_attachment.reset(m_attachment.release());
|
||||
m_attachment.reset(filter);
|
||||
NotifyAttachmentChange();
|
||||
}
|
||||
|
||||
unsigned int Filter::CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end, const std::string &channel, bool blocking) const
|
||||
{
|
||||
return AttachedTransformation()->CopyRangeTo2(target, begin, end, channel, blocking);
|
||||
}
|
||||
|
||||
unsigned int Filter::TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel, bool blocking)
|
||||
{
|
||||
return AttachedTransformation()->TransferTo2(target, transferBytes, channel, blocking);
|
||||
}
|
||||
|
||||
void Filter::Initialize(const NameValuePairs ¶meters, int propagation)
|
||||
{
|
||||
m_continueAt = 0;
|
||||
IsolatedInitialize(parameters);
|
||||
PropagateInitialize(parameters, propagation);
|
||||
}
|
||||
|
||||
bool Filter::Flush(bool hardFlush, int propagation, bool blocking)
|
||||
{
|
||||
switch (m_continueAt)
|
||||
{
|
||||
case 0:
|
||||
if (IsolatedFlush(hardFlush, blocking))
|
||||
return true;
|
||||
case 1:
|
||||
if (OutputFlush(1, hardFlush, propagation, blocking))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Filter::MessageSeriesEnd(int propagation, bool blocking)
|
||||
{
|
||||
switch (m_continueAt)
|
||||
{
|
||||
case 0:
|
||||
if (IsolatedMessageSeriesEnd(blocking))
|
||||
return true;
|
||||
case 1:
|
||||
if (ShouldPropagateMessageSeriesEnd() && OutputMessageSeriesEnd(1, propagation, blocking))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Filter::PropagateInitialize(const NameValuePairs ¶meters, int propagation, const std::string &channel)
|
||||
{
|
||||
if (propagation)
|
||||
AttachedTransformation()->ChannelInitialize(channel, parameters, propagation-1);
|
||||
}
|
||||
|
||||
unsigned int Filter::Output(int outputSite, const byte *inString, unsigned int length, int messageEnd, bool blocking, const std::string &channel)
|
||||
{
|
||||
if (messageEnd)
|
||||
messageEnd--;
|
||||
unsigned int result = AttachedTransformation()->Put2(inString, length, messageEnd, blocking);
|
||||
m_continueAt = result ? outputSite : 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Filter::OutputFlush(int outputSite, bool hardFlush, int propagation, bool blocking, const std::string &channel)
|
||||
{
|
||||
if (propagation && AttachedTransformation()->ChannelFlush(channel, hardFlush, propagation-1, blocking))
|
||||
{
|
||||
m_continueAt = outputSite;
|
||||
return true;
|
||||
}
|
||||
m_continueAt = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Filter::OutputMessageSeriesEnd(int outputSite, int propagation, bool blocking, const std::string &channel)
|
||||
{
|
||||
if (propagation && AttachedTransformation()->ChannelMessageSeriesEnd(channel, propagation-1, blocking))
|
||||
{
|
||||
m_continueAt = outputSite;
|
||||
return true;
|
||||
}
|
||||
m_continueAt = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
|
||||
unsigned int MeterFilter::Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking)
|
||||
{
|
||||
if (m_transparent)
|
||||
{
|
||||
FILTER_BEGIN;
|
||||
m_currentMessageBytes += length;
|
||||
m_totalBytes += length;
|
||||
|
||||
if (messageEnd)
|
||||
{
|
||||
m_currentMessageBytes = 0;
|
||||
m_currentSeriesMessages++;
|
||||
m_totalMessages++;
|
||||
}
|
||||
|
||||
FILTER_OUTPUT(1, begin, length, messageEnd);
|
||||
FILTER_END_NO_MESSAGE_END;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool MeterFilter::IsolatedMessageSeriesEnd(bool blocking)
|
||||
{
|
||||
m_currentMessageBytes = 0;
|
||||
m_currentSeriesMessages = 0;
|
||||
m_totalMessageSeries++;
|
||||
return false;
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
|
||||
void FilterWithBufferedInput::BlockQueue::ResetQueue(unsigned int blockSize, unsigned int maxBlocks)
|
||||
{
|
||||
m_buffer.New(blockSize * maxBlocks);
|
||||
m_blockSize = blockSize;
|
||||
m_maxBlocks = maxBlocks;
|
||||
m_size = 0;
|
||||
m_begin = m_buffer;
|
||||
}
|
||||
|
||||
byte *FilterWithBufferedInput::BlockQueue::GetBlock()
|
||||
{
|
||||
if (m_size >= m_blockSize)
|
||||
{
|
||||
byte *ptr = m_begin;
|
||||
if ((m_begin+=m_blockSize) == m_buffer.end())
|
||||
m_begin = m_buffer;
|
||||
m_size -= m_blockSize;
|
||||
return ptr;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
byte *FilterWithBufferedInput::BlockQueue::GetContigousBlocks(unsigned int &numberOfBytes)
|
||||
{
|
||||
numberOfBytes = STDMIN(numberOfBytes, STDMIN((unsigned int)(m_buffer.end()-m_begin), m_size));
|
||||
byte *ptr = m_begin;
|
||||
m_begin += numberOfBytes;
|
||||
m_size -= numberOfBytes;
|
||||
if (m_size == 0 || m_begin == m_buffer.end())
|
||||
m_begin = m_buffer;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
unsigned int FilterWithBufferedInput::BlockQueue::GetAll(byte *outString)
|
||||
{
|
||||
unsigned int size = m_size;
|
||||
unsigned int numberOfBytes = m_maxBlocks*m_blockSize;
|
||||
const byte *ptr = GetContigousBlocks(numberOfBytes);
|
||||
memcpy(outString, ptr, numberOfBytes);
|
||||
memcpy(outString+numberOfBytes, m_begin, m_size);
|
||||
m_size = 0;
|
||||
return size;
|
||||
}
|
||||
|
||||
void FilterWithBufferedInput::BlockQueue::Put(const byte *inString, unsigned int length)
|
||||
{
|
||||
assert(m_size + length <= m_buffer.size());
|
||||
byte *end = (m_size < (unsigned int)(m_buffer.end()-m_begin)) ? m_begin + m_size : m_begin + m_size - m_buffer.size();
|
||||
unsigned int len = STDMIN(length, (unsigned int)(m_buffer.end()-end));
|
||||
memcpy(end, inString, len);
|
||||
if (len < length)
|
||||
memcpy(m_buffer, inString+len, length-len);
|
||||
m_size += length;
|
||||
}
|
||||
|
||||
FilterWithBufferedInput::FilterWithBufferedInput(BufferedTransformation *attachment)
|
||||
: Filter(attachment)
|
||||
{
|
||||
}
|
||||
|
||||
FilterWithBufferedInput::FilterWithBufferedInput(unsigned int firstSize, unsigned int blockSize, unsigned int lastSize, BufferedTransformation *attachment)
|
||||
: Filter(attachment), m_firstSize(firstSize), m_blockSize(blockSize), m_lastSize(lastSize)
|
||||
, m_firstInputDone(false)
|
||||
{
|
||||
ASSERT( m_firstSize >= 0 );
|
||||
ASSERT( m_blockSize >= 1 );
|
||||
ASSERT( m_lastSize >= 0 );
|
||||
|
||||
m_queue.ResetQueue(1, m_firstSize);
|
||||
}
|
||||
|
||||
void FilterWithBufferedInput::IsolatedInitialize(const NameValuePairs ¶meters)
|
||||
{
|
||||
InitializeDerivedAndReturnNewSizes(parameters, m_firstSize, m_blockSize, m_lastSize);
|
||||
ASSERT( m_firstSize >= 0 );
|
||||
ASSERT( m_blockSize >= 1 );
|
||||
ASSERT( m_lastSize >= 0 );
|
||||
m_queue.ResetQueue(1, m_firstSize);
|
||||
m_firstInputDone = false;
|
||||
}
|
||||
|
||||
bool FilterWithBufferedInput::IsolatedFlush(bool hardFlush, bool blocking)
|
||||
{
|
||||
if (!blocking)
|
||||
throw BlockingInputOnly("FilterWithBufferedInput");
|
||||
|
||||
if (hardFlush)
|
||||
ForceNextPut();
|
||||
FlushDerived();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int FilterWithBufferedInput::PutMaybeModifiable(byte *inString, unsigned int length, int messageEnd, bool blocking, bool modifiable)
|
||||
{
|
||||
if (!blocking)
|
||||
throw BlockingInputOnly("FilterWithBufferedInput");
|
||||
|
||||
if (length != 0)
|
||||
{
|
||||
unsigned int newLength = m_queue.CurrentSize() + length;
|
||||
|
||||
if (!m_firstInputDone && newLength >= m_firstSize)
|
||||
{
|
||||
unsigned int len = m_firstSize - m_queue.CurrentSize();
|
||||
m_queue.Put(inString, len);
|
||||
FirstPut(m_queue.GetContigousBlocks(m_firstSize));
|
||||
assert(m_queue.CurrentSize() == 0);
|
||||
m_queue.ResetQueue(m_blockSize, (2*m_blockSize+m_lastSize-2)/m_blockSize);
|
||||
|
||||
inString += len;
|
||||
newLength -= m_firstSize;
|
||||
m_firstInputDone = true;
|
||||
}
|
||||
|
||||
if (m_firstInputDone)
|
||||
{
|
||||
if (m_blockSize == 1)
|
||||
{
|
||||
while (newLength > m_lastSize && m_queue.CurrentSize() > 0)
|
||||
{
|
||||
unsigned int len = newLength - m_lastSize;
|
||||
byte *ptr = m_queue.GetContigousBlocks(len);
|
||||
NextPutModifiable(ptr, len);
|
||||
newLength -= len;
|
||||
}
|
||||
|
||||
if (newLength > m_lastSize)
|
||||
{
|
||||
unsigned int len = newLength - m_lastSize;
|
||||
NextPutMaybeModifiable(inString, len, modifiable);
|
||||
inString += len;
|
||||
newLength -= len;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (newLength >= m_blockSize + m_lastSize && m_queue.CurrentSize() >= m_blockSize)
|
||||
{
|
||||
NextPutModifiable(m_queue.GetBlock(), m_blockSize);
|
||||
newLength -= m_blockSize;
|
||||
}
|
||||
|
||||
if (newLength >= m_blockSize + m_lastSize && m_queue.CurrentSize() > 0)
|
||||
{
|
||||
assert(m_queue.CurrentSize() < m_blockSize);
|
||||
unsigned int len = m_blockSize - m_queue.CurrentSize();
|
||||
m_queue.Put(inString, len);
|
||||
inString += len;
|
||||
NextPutModifiable(m_queue.GetBlock(), m_blockSize);
|
||||
newLength -= m_blockSize;
|
||||
}
|
||||
|
||||
if (newLength >= m_blockSize + m_lastSize)
|
||||
{
|
||||
unsigned int len = RoundDownToMultipleOf(newLength - m_lastSize, m_blockSize);
|
||||
NextPutMaybeModifiable(inString, len, modifiable);
|
||||
inString += len;
|
||||
newLength -= len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_queue.Put(inString, newLength - m_queue.CurrentSize());
|
||||
}
|
||||
|
||||
if (messageEnd)
|
||||
{
|
||||
if (!m_firstInputDone && m_firstSize==0)
|
||||
FirstPut(NULL);
|
||||
|
||||
SecByteBlock temp(m_queue.CurrentSize());
|
||||
m_queue.GetAll(temp);
|
||||
LastPut(temp, temp.size());
|
||||
|
||||
m_firstInputDone = false;
|
||||
m_queue.ResetQueue(1, m_firstSize);
|
||||
|
||||
Output(1, NULL, 0, messageEnd, blocking);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FilterWithBufferedInput::ForceNextPut()
|
||||
{
|
||||
if (!m_firstInputDone)
|
||||
return;
|
||||
|
||||
if (m_blockSize > 1)
|
||||
{
|
||||
while (m_queue.CurrentSize() >= m_blockSize)
|
||||
NextPutModifiable(m_queue.GetBlock(), m_blockSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int len;
|
||||
while ((len = m_queue.CurrentSize()) > 0)
|
||||
NextPutModifiable(m_queue.GetContigousBlocks(len), len);
|
||||
}
|
||||
}
|
||||
|
||||
void FilterWithBufferedInput::NextPutMultiple(const byte *inString, unsigned int length)
|
||||
{
|
||||
assert(m_blockSize > 1); // m_blockSize = 1 should always override this function
|
||||
while (length > 0)
|
||||
{
|
||||
assert(length >= m_blockSize);
|
||||
NextPutSingle(inString);
|
||||
inString += m_blockSize;
|
||||
length -= m_blockSize;
|
||||
}
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
|
||||
void Redirector::ChannelInitialize(const std::string &channel, const NameValuePairs ¶meters, int propagation)
|
||||
{
|
||||
if (channel.empty())
|
||||
{
|
||||
m_target = parameters.GetValueWithDefault("RedirectionTargetPointer", (BufferedTransformation*)NULL);
|
||||
m_passSignal = parameters.GetValueWithDefault("PassSignal", true);
|
||||
}
|
||||
|
||||
if (m_target && m_passSignal)
|
||||
m_target->ChannelInitialize(channel, parameters, propagation);
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
|
||||
unsigned int ArraySink::Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking)
|
||||
{
|
||||
memcpy(m_buf+m_total, begin, STDMIN(length, SaturatingSubtract(m_size, m_total)));
|
||||
m_total += length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
byte * ArraySink::CreatePutSpace(unsigned int &size)
|
||||
{
|
||||
size = m_size - m_total;
|
||||
return m_buf + m_total;
|
||||
}
|
||||
|
||||
void ArraySink::IsolatedInitialize(const NameValuePairs ¶meters)
|
||||
{
|
||||
ByteArrayParameter array;
|
||||
if (!parameters.GetValue(Name::OutputBuffer(), array))
|
||||
throw InvalidArgument("ArraySink: missing OutputBuffer argument");
|
||||
m_buf = array.begin();
|
||||
m_size = array.size();
|
||||
m_total = 0;
|
||||
}
|
||||
|
||||
unsigned int ArrayXorSink::Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking)
|
||||
{
|
||||
xorbuf(m_buf+m_total, begin, STDMIN(length, SaturatingSubtract(m_size, m_total)));
|
||||
m_total += length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
|
||||
void HashFilter::IsolatedInitialize(const NameValuePairs ¶meters)
|
||||
{
|
||||
m_putMessage = parameters.GetValueWithDefault(Name::PutMessage(), false);
|
||||
m_hashModule.Restart();
|
||||
}
|
||||
|
||||
unsigned int HashFilter::Put2(const byte *inString, unsigned int length, int messageEnd, bool blocking)
|
||||
{
|
||||
FILTER_BEGIN;
|
||||
m_hashModule.Update(inString, length);
|
||||
if (m_putMessage)
|
||||
FILTER_OUTPUT(1, inString, length, 0);
|
||||
if (messageEnd)
|
||||
{
|
||||
{
|
||||
unsigned int size, digestSize = m_hashModule.DigestSize();
|
||||
m_space = HelpCreatePutSpace(*AttachedTransformation(), NULL_CHANNEL, digestSize, digestSize, size = digestSize);
|
||||
m_hashModule.Final(m_space);
|
||||
}
|
||||
FILTER_OUTPUT(2, m_space, m_hashModule.DigestSize(), messageEnd);
|
||||
}
|
||||
FILTER_END_NO_MESSAGE_END;
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
|
||||
void SignerFilter::IsolatedInitialize(const NameValuePairs ¶meters)
|
||||
{
|
||||
m_putMessage = parameters.GetValueWithDefault(Name::PutMessage(), false);
|
||||
m_messageAccumulator.reset(m_signer.NewSignatureAccumulator());
|
||||
}
|
||||
|
||||
unsigned int SignerFilter::Put2(const byte *inString, unsigned int length, int messageEnd, bool blocking)
|
||||
{
|
||||
FILTER_BEGIN;
|
||||
m_messageAccumulator->Update(inString, length);
|
||||
if (m_putMessage)
|
||||
FILTER_OUTPUT(1, inString, length, 0);
|
||||
if (messageEnd)
|
||||
{
|
||||
m_buf.New(m_signer.SignatureLength());
|
||||
m_signer.Sign(m_rng, m_messageAccumulator.release(), m_buf);
|
||||
FILTER_OUTPUT(2, m_buf, m_buf.size(), messageEnd);
|
||||
m_messageAccumulator.reset(m_signer.NewSignatureAccumulator());
|
||||
}
|
||||
FILTER_END_NO_MESSAGE_END;
|
||||
}
|
||||
|
||||
SignatureVerificationFilter::SignatureVerificationFilter(const PK_Verifier &verifier, BufferedTransformation *attachment, word32 flags)
|
||||
: FilterWithBufferedInput(attachment)
|
||||
, m_verifier(verifier)
|
||||
{
|
||||
IsolatedInitialize(MakeParameters(Name::SignatureVerificationFilterFlags(), flags));
|
||||
}
|
||||
|
||||
void SignatureVerificationFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, unsigned int &firstSize, unsigned int &blockSize, unsigned int &lastSize)
|
||||
{
|
||||
m_flags = parameters.GetValueWithDefault(Name::SignatureVerificationFilterFlags(), (word32)DEFAULT_FLAGS);
|
||||
m_messageAccumulator.reset(m_verifier.NewVerificationAccumulator());
|
||||
unsigned int size = m_verifier.SignatureLength();
|
||||
assert(size != 0); // TODO: handle recoverable signature scheme
|
||||
m_verified = false;
|
||||
firstSize = m_flags & SIGNATURE_AT_BEGIN ? size : 0;
|
||||
blockSize = 1;
|
||||
lastSize = m_flags & SIGNATURE_AT_BEGIN ? 0 : size;
|
||||
}
|
||||
|
||||
void SignatureVerificationFilter::FirstPut(const byte *inString)
|
||||
{
|
||||
if (m_flags & SIGNATURE_AT_BEGIN)
|
||||
{
|
||||
if (m_verifier.SignatureUpfront())
|
||||
m_verifier.InputSignature(*m_messageAccumulator, inString, m_verifier.SignatureLength());
|
||||
else
|
||||
{
|
||||
m_signature.New(m_verifier.SignatureLength());
|
||||
memcpy(m_signature, inString, m_signature.size());
|
||||
}
|
||||
|
||||
if (m_flags & PUT_SIGNATURE)
|
||||
AttachedTransformation()->Put(inString, m_signature.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(!m_verifier.SignatureUpfront());
|
||||
}
|
||||
}
|
||||
|
||||
void SignatureVerificationFilter::NextPutMultiple(const byte *inString, unsigned int length)
|
||||
{
|
||||
m_messageAccumulator->Update(inString, length);
|
||||
if (m_flags & PUT_MESSAGE)
|
||||
AttachedTransformation()->Put(inString, length);
|
||||
}
|
||||
|
||||
void SignatureVerificationFilter::LastPut(const byte *inString, unsigned int length)
|
||||
{
|
||||
if (m_flags & SIGNATURE_AT_BEGIN)
|
||||
{
|
||||
assert(length == 0);
|
||||
m_verifier.InputSignature(*m_messageAccumulator, m_signature, m_signature.size());
|
||||
m_verified = m_verifier.VerifyAndRestart(*m_messageAccumulator);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_verifier.InputSignature(*m_messageAccumulator, inString, length);
|
||||
m_verified = m_verifier.VerifyAndRestart(*m_messageAccumulator);
|
||||
if (m_flags & PUT_SIGNATURE)
|
||||
AttachedTransformation()->Put(inString, length);
|
||||
}
|
||||
|
||||
if (m_flags & PUT_RESULT)
|
||||
AttachedTransformation()->Put(m_verified);
|
||||
|
||||
if ((m_flags & THROW_EXCEPTION) && !m_verified)
|
||||
throw SignatureVerificationFailed();
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
|
||||
unsigned int Source::PumpAll2(bool blocking)
|
||||
{
|
||||
// TODO: switch length type
|
||||
unsigned long i = UINT_MAX;
|
||||
RETURN_IF_NONZERO(Pump2(i, blocking));
|
||||
unsigned int j = UINT_MAX;
|
||||
return PumpMessages2(j, blocking);
|
||||
}
|
||||
|
||||
bool Store::GetNextMessage()
|
||||
{
|
||||
if (!m_messageEnd && !AnyRetrievable())
|
||||
{
|
||||
m_messageEnd=true;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int Store::CopyMessagesTo(BufferedTransformation &target, unsigned int count, const std::string &channel) const
|
||||
{
|
||||
if (m_messageEnd || count == 0)
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
CopyTo(target, ULONG_MAX, channel);
|
||||
if (GetAutoSignalPropagation())
|
||||
target.ChannelMessageEnd(channel, GetAutoSignalPropagation()-1);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
void StringStore::StoreInitialize(const NameValuePairs ¶meters)
|
||||
{
|
||||
ConstByteArrayParameter array;
|
||||
if (!parameters.GetValue(Name::InputBuffer(), array))
|
||||
throw InvalidArgument("StringStore: missing InputBuffer argument");
|
||||
m_store = array.begin();
|
||||
m_length = array.size();
|
||||
m_count = 0;
|
||||
}
|
||||
|
||||
unsigned int StringStore::TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel, bool blocking)
|
||||
{
|
||||
unsigned long position = 0;
|
||||
unsigned int blockedBytes = CopyRangeTo2(target, position, transferBytes, channel, blocking);
|
||||
m_count += position;
|
||||
transferBytes = position;
|
||||
return blockedBytes;
|
||||
}
|
||||
|
||||
unsigned int StringStore::CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end, const std::string &channel, bool blocking) const
|
||||
{
|
||||
unsigned int i = (unsigned int)STDMIN((unsigned long)m_count+begin, (unsigned long)m_length);
|
||||
unsigned int len = (unsigned int)STDMIN((unsigned long)m_length-i, end-begin);
|
||||
unsigned int blockedBytes = target.ChannelPut2(channel, m_store+i, len, 0, blocking);
|
||||
if (!blockedBytes)
|
||||
begin += len;
|
||||
return blockedBytes;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,537 +0,0 @@
|
||||
#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 CryptoPP {
|
||||
|
||||
/// provides an implementation of BufferedTransformation's attachment interface
|
||||
class Filter : public BufferedTransformation, public NotCopyable
|
||||
{
|
||||
public:
|
||||
Filter(BufferedTransformation *attachment);
|
||||
|
||||
bool Attachable() {return true;}
|
||||
BufferedTransformation *AttachedTransformation();
|
||||
const BufferedTransformation *AttachedTransformation() const;
|
||||
void Detach(BufferedTransformation *newAttachment = NULL);
|
||||
|
||||
unsigned int TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel=NULL_CHANNEL, bool blocking=true);
|
||||
unsigned int CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end=ULONG_MAX, const std::string &channel=NULL_CHANNEL, bool blocking=true) const;
|
||||
|
||||
void Initialize(const NameValuePairs ¶meters=g_nullNameValuePairs, int propagation=-1);
|
||||
bool Flush(bool hardFlush, int propagation=-1, bool blocking=true);
|
||||
bool MessageSeriesEnd(int propagation=-1, bool blocking=true);
|
||||
|
||||
protected:
|
||||
virtual void NotifyAttachmentChange() {}
|
||||
virtual BufferedTransformation * NewDefaultAttachment() const;
|
||||
void Insert(Filter *nextFilter); // insert filter after this one
|
||||
|
||||
virtual bool ShouldPropagateMessageEnd() const {return true;}
|
||||
virtual bool ShouldPropagateMessageSeriesEnd() const {return true;}
|
||||
|
||||
void PropagateInitialize(const NameValuePairs ¶meters, int propagation, const std::string &channel=NULL_CHANNEL);
|
||||
|
||||
unsigned int Output(int outputSite, const byte *inString, unsigned int length, int messageEnd, bool blocking, const std::string &channel=NULL_CHANNEL);
|
||||
bool OutputMessageEnd(int outputSite, int propagation, bool blocking, const std::string &channel=NULL_CHANNEL);
|
||||
bool OutputFlush(int outputSite, bool hardFlush, int propagation, bool blocking, const std::string &channel=NULL_CHANNEL);
|
||||
bool OutputMessageSeriesEnd(int outputSite, int propagation, bool blocking, const std::string &channel=NULL_CHANNEL);
|
||||
|
||||
private:
|
||||
member_ptr<BufferedTransformation> m_attachment;
|
||||
|
||||
protected:
|
||||
unsigned int m_inputPosition;
|
||||
int m_continueAt;
|
||||
};
|
||||
|
||||
struct FilterPutSpaceHelper
|
||||
{
|
||||
// desiredSize is how much to ask target, bufferSize is how much to allocate in m_tempSpace
|
||||
byte *HelpCreatePutSpace(BufferedTransformation &target, const std::string &channel, unsigned int minSize, unsigned int desiredSize, unsigned int &bufferSize)
|
||||
{
|
||||
assert(desiredSize >= minSize && bufferSize >= minSize);
|
||||
if (m_tempSpace.size() < minSize)
|
||||
{
|
||||
byte *result = target.ChannelCreatePutSpace(channel, desiredSize);
|
||||
if (desiredSize >= minSize)
|
||||
{
|
||||
bufferSize = desiredSize;
|
||||
return result;
|
||||
}
|
||||
m_tempSpace.New(bufferSize);
|
||||
}
|
||||
|
||||
bufferSize = m_tempSpace.size();
|
||||
return m_tempSpace.begin();
|
||||
}
|
||||
byte *HelpCreatePutSpace(BufferedTransformation &target, const std::string &channel, unsigned int minSize)
|
||||
{return HelpCreatePutSpace(target, channel, minSize, minSize, minSize);}
|
||||
byte *HelpCreatePutSpace(BufferedTransformation &target, const std::string &channel, unsigned int minSize, unsigned int bufferSize)
|
||||
{return HelpCreatePutSpace(target, channel, minSize, minSize, bufferSize);}
|
||||
SecByteBlock m_tempSpace;
|
||||
};
|
||||
|
||||
//! measure how many byte and messages pass through, also serves as valve
|
||||
class MeterFilter : public Bufferless<Filter>
|
||||
{
|
||||
public:
|
||||
MeterFilter(BufferedTransformation *attachment=NULL, bool transparent=true)
|
||||
: Bufferless<Filter>(attachment), m_transparent(transparent) {ResetMeter();}
|
||||
|
||||
void SetTransparent(bool transparent) {m_transparent = transparent;}
|
||||
void ResetMeter() {m_currentMessageBytes = m_totalBytes = m_currentSeriesMessages = m_totalMessages = m_totalMessageSeries = 0;}
|
||||
|
||||
unsigned long GetCurrentMessageBytes() const {return m_currentMessageBytes;}
|
||||
unsigned long GetTotalBytes() {return m_totalBytes;}
|
||||
unsigned int GetCurrentSeriesMessages() {return m_currentSeriesMessages;}
|
||||
unsigned int GetTotalMessages() {return m_totalMessages;}
|
||||
unsigned int GetTotalMessageSeries() {return m_totalMessageSeries;}
|
||||
|
||||
unsigned int Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking);
|
||||
bool IsolatedMessageSeriesEnd(bool blocking);
|
||||
|
||||
private:
|
||||
bool ShouldPropagateMessageEnd() const {return m_transparent;}
|
||||
bool ShouldPropagateMessageSeriesEnd() const {return m_transparent;}
|
||||
|
||||
bool m_transparent;
|
||||
unsigned long m_currentMessageBytes, m_totalBytes;
|
||||
unsigned int m_currentSeriesMessages, m_totalMessages, m_totalMessageSeries;
|
||||
};
|
||||
|
||||
//! .
|
||||
class TransparentFilter : public MeterFilter
|
||||
{
|
||||
public:
|
||||
TransparentFilter(BufferedTransformation *attachment=NULL) : MeterFilter(attachment, true) {}
|
||||
};
|
||||
|
||||
//! .
|
||||
class OpaqueFilter : public MeterFilter
|
||||
{
|
||||
public:
|
||||
OpaqueFilter(BufferedTransformation *attachment=NULL) : MeterFilter(attachment, false) {}
|
||||
};
|
||||
|
||||
/*! FilterWithBufferedInput divides up the input stream into
|
||||
a first block, a number of middle blocks, and a last block.
|
||||
First and last blocks are optional, and middle blocks may
|
||||
be a stream instead (i.e. blockSize == 1).
|
||||
*/
|
||||
class FilterWithBufferedInput : public Filter
|
||||
{
|
||||
public:
|
||||
FilterWithBufferedInput(BufferedTransformation *attachment);
|
||||
//! firstSize and lastSize may be 0, blockSize must be at least 1
|
||||
FilterWithBufferedInput(unsigned int firstSize, unsigned int blockSize, unsigned int lastSize, BufferedTransformation *attachment);
|
||||
|
||||
void IsolatedInitialize(const NameValuePairs ¶meters);
|
||||
unsigned int Put2(const byte *inString, unsigned int length, int messageEnd, bool blocking)
|
||||
{
|
||||
return PutMaybeModifiable(const_cast<byte *>(inString), length, messageEnd, blocking, false);
|
||||
}
|
||||
unsigned int PutModifiable2(byte *inString, unsigned int length, int messageEnd, bool blocking)
|
||||
{
|
||||
return PutMaybeModifiable(inString, length, messageEnd, blocking, true);
|
||||
}
|
||||
/*! calls ForceNextPut() if hardFlush is true */
|
||||
bool IsolatedFlush(bool hardFlush, bool blocking);
|
||||
|
||||
/*! The input buffer may contain more than blockSize bytes if lastSize != 0.
|
||||
ForceNextPut() forces a call to NextPut() if this is the case.
|
||||
*/
|
||||
void ForceNextPut();
|
||||
|
||||
protected:
|
||||
bool DidFirstPut() {return m_firstInputDone;}
|
||||
|
||||
virtual void InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, unsigned int &firstSize, unsigned int &blockSize, unsigned int &lastSize)
|
||||
{InitializeDerived(parameters);}
|
||||
virtual void InitializeDerived(const NameValuePairs ¶meters) {}
|
||||
// FirstPut() is called if (firstSize != 0 and totalLength >= firstSize)
|
||||
// or (firstSize == 0 and (totalLength > 0 or a MessageEnd() is received))
|
||||
virtual void FirstPut(const byte *inString) =0;
|
||||
// NextPut() is called if totalLength >= firstSize+blockSize+lastSize
|
||||
virtual void NextPutSingle(const byte *inString) {assert(false);}
|
||||
// Same as NextPut() except length can be a multiple of blockSize
|
||||
// Either NextPut() or NextPutMultiple() must be overriden
|
||||
virtual void NextPutMultiple(const byte *inString, unsigned int length);
|
||||
// Same as NextPutMultiple(), but inString can be modified
|
||||
virtual void NextPutModifiable(byte *inString, unsigned int length)
|
||||
{NextPutMultiple(inString, length);}
|
||||
// LastPut() is always called
|
||||
// if totalLength < firstSize then length == totalLength
|
||||
// else if totalLength <= firstSize+lastSize then length == totalLength-firstSize
|
||||
// else lastSize <= length < lastSize+blockSize
|
||||
virtual void LastPut(const byte *inString, unsigned int length) =0;
|
||||
virtual void FlushDerived() {}
|
||||
|
||||
private:
|
||||
unsigned int PutMaybeModifiable(byte *begin, unsigned int length, int messageEnd, bool blocking, bool modifiable);
|
||||
void NextPutMaybeModifiable(byte *inString, unsigned int length, bool modifiable)
|
||||
{
|
||||
if (modifiable) NextPutModifiable(inString, length);
|
||||
else NextPutMultiple(inString, length);
|
||||
}
|
||||
|
||||
// This function should no longer be used, put this here to cause a compiler error
|
||||
// if someone tries to override NextPut().
|
||||
virtual int NextPut(const byte *inString, unsigned int length) {assert(false); return 0;}
|
||||
|
||||
class BlockQueue
|
||||
{
|
||||
public:
|
||||
void ResetQueue(unsigned int blockSize, unsigned int maxBlocks);
|
||||
byte *GetBlock();
|
||||
byte *GetContigousBlocks(unsigned int &numberOfBytes);
|
||||
unsigned int GetAll(byte *outString);
|
||||
void Put(const byte *inString, unsigned int length);
|
||||
unsigned int CurrentSize() const {return m_size;}
|
||||
unsigned int MaxSize() const {return m_buffer.size();}
|
||||
|
||||
private:
|
||||
SecByteBlock m_buffer;
|
||||
unsigned int m_blockSize, m_maxBlocks, m_size;
|
||||
byte *m_begin;
|
||||
};
|
||||
|
||||
unsigned int m_firstSize, m_blockSize, m_lastSize;
|
||||
bool m_firstInputDone;
|
||||
BlockQueue m_queue;
|
||||
};
|
||||
|
||||
//! .
|
||||
class FilterWithInputQueue : public Filter
|
||||
{
|
||||
public:
|
||||
FilterWithInputQueue(BufferedTransformation *attachment) : Filter(attachment) {}
|
||||
unsigned int Put2(const byte *inString, unsigned int length, int messageEnd, bool blocking)
|
||||
{
|
||||
if (!blocking)
|
||||
throw BlockingInputOnly("FilterWithInputQueue");
|
||||
|
||||
m_inQueue.Put(inString, length);
|
||||
if (messageEnd)
|
||||
{
|
||||
IsolatedMessageEnd(blocking);
|
||||
Output(0, NULL, 0, messageEnd, blocking);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool IsolatedMessageEnd(bool blocking) =0;
|
||||
void IsolatedInitialize(const NameValuePairs ¶meters) {m_inQueue.Clear();}
|
||||
|
||||
ByteQueue m_inQueue;
|
||||
};
|
||||
|
||||
//! Filter Wrapper for HashTransformation
|
||||
class HashFilter : public Bufferless<Filter>, private FilterPutSpaceHelper
|
||||
{
|
||||
public:
|
||||
HashFilter(HashTransformation &hm, BufferedTransformation *attachment = NULL, bool putMessage=false)
|
||||
: Bufferless<Filter>(attachment), m_hashModule(hm), m_putMessage(putMessage) {}
|
||||
|
||||
void IsolatedInitialize(const NameValuePairs ¶meters);
|
||||
unsigned int Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking);
|
||||
|
||||
byte * CreatePutSpace(unsigned int &size) {return m_hashModule.CreateUpdateSpace(size);}
|
||||
|
||||
private:
|
||||
HashTransformation &m_hashModule;
|
||||
bool m_putMessage;
|
||||
byte *m_space;
|
||||
};
|
||||
|
||||
//! Filter Wrapper for PK_Signer
|
||||
class SignerFilter : public Unflushable<Filter>
|
||||
{
|
||||
public:
|
||||
SignerFilter(RandomNumberGenerator &rng, const PK_Signer &signer, BufferedTransformation *attachment = NULL, bool putMessage=false)
|
||||
: Unflushable<Filter>(attachment), m_rng(rng), m_signer(signer), m_messageAccumulator(signer.NewSignatureAccumulator()), m_putMessage(putMessage) {}
|
||||
|
||||
void IsolatedInitialize(const NameValuePairs ¶meters);
|
||||
unsigned int Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking);
|
||||
|
||||
private:
|
||||
RandomNumberGenerator &m_rng;
|
||||
const PK_Signer &m_signer;
|
||||
member_ptr<PK_MessageAccumulator> m_messageAccumulator;
|
||||
bool m_putMessage;
|
||||
SecByteBlock m_buf;
|
||||
};
|
||||
|
||||
//! Filter Wrapper for PK_Verifier
|
||||
class SignatureVerificationFilter : public FilterWithBufferedInput
|
||||
{
|
||||
public:
|
||||
class SignatureVerificationFailed : public Exception
|
||||
{
|
||||
public:
|
||||
SignatureVerificationFailed()
|
||||
: Exception(DATA_INTEGRITY_CHECK_FAILED, "VerifierFilter: digital signature not valid") {}
|
||||
};
|
||||
|
||||
enum Flags {SIGNATURE_AT_BEGIN=1, PUT_MESSAGE=2, PUT_SIGNATURE=4, PUT_RESULT=8, THROW_EXCEPTION=16, DEFAULT_FLAGS = SIGNATURE_AT_BEGIN | PUT_RESULT};
|
||||
SignatureVerificationFilter(const PK_Verifier &verifier, BufferedTransformation *attachment = NULL, word32 flags = DEFAULT_FLAGS);
|
||||
|
||||
bool GetLastResult() const {return m_verified;}
|
||||
|
||||
protected:
|
||||
void InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, unsigned int &firstSize, unsigned int &blockSize, unsigned int &lastSize);
|
||||
void FirstPut(const byte *inString);
|
||||
void NextPutMultiple(const byte *inString, unsigned int length);
|
||||
void LastPut(const byte *inString, unsigned int length);
|
||||
|
||||
private:
|
||||
const PK_Verifier &m_verifier;
|
||||
member_ptr<PK_MessageAccumulator> m_messageAccumulator;
|
||||
word32 m_flags;
|
||||
SecByteBlock m_signature;
|
||||
bool m_verified;
|
||||
};
|
||||
|
||||
typedef SignatureVerificationFilter VerifierFilter; // for backwards compatibility
|
||||
|
||||
//! Redirect input to another BufferedTransformation without owning it
|
||||
class Redirector : public CustomSignalPropagation<Sink>
|
||||
{
|
||||
public:
|
||||
Redirector() : m_target(NULL), m_passSignal(true) {}
|
||||
Redirector(BufferedTransformation &target, bool passSignal=true) : m_target(&target), m_passSignal(passSignal) {}
|
||||
|
||||
void Redirect(BufferedTransformation &target) {m_target = ⌖}
|
||||
void StopRedirection() {m_target = NULL;}
|
||||
bool GetPassSignal() const {return m_passSignal;}
|
||||
void SetPassSignal(bool passSignal) {m_passSignal = passSignal;}
|
||||
|
||||
unsigned int Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking)
|
||||
{return m_target ? m_target->Put2(begin, length, m_passSignal ? messageEnd : 0, blocking) : 0;}
|
||||
void Initialize(const NameValuePairs ¶meters, int propagation)
|
||||
{ChannelInitialize(NULL_CHANNEL, parameters, propagation);}
|
||||
bool Flush(bool hardFlush, int propagation=-1, bool blocking=true)
|
||||
{return m_target && m_passSignal ? m_target->Flush(hardFlush, propagation, blocking) : false;}
|
||||
bool MessageSeriesEnd(int propagation=-1, bool blocking=true)
|
||||
{return m_target && m_passSignal ? m_target->MessageSeriesEnd(propagation, blocking) : false;}
|
||||
|
||||
void ChannelInitialize(const std::string &channel, const NameValuePairs ¶meters=g_nullNameValuePairs, int propagation=-1);
|
||||
unsigned int ChannelPut2(const std::string &channel, const byte *begin, unsigned int length, int messageEnd, bool blocking)
|
||||
{return m_target ? m_target->ChannelPut2(channel, begin, length, m_passSignal ? messageEnd : 0, blocking) : 0;}
|
||||
unsigned int ChannelPutModifiable2(const std::string &channel, byte *begin, unsigned int length, int messageEnd, bool blocking)
|
||||
{return m_target ? m_target->ChannelPutModifiable2(channel, begin, length, m_passSignal ? messageEnd : 0, blocking) : 0;}
|
||||
bool ChannelFlush(const std::string &channel, bool completeFlush, int propagation=-1, bool blocking=true)
|
||||
{return m_target && m_passSignal ? m_target->ChannelFlush(channel, completeFlush, propagation, blocking) : false;}
|
||||
bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true)
|
||||
{return m_target && m_passSignal ? m_target->ChannelMessageSeriesEnd(channel, propagation, blocking) : false;}
|
||||
|
||||
private:
|
||||
BufferedTransformation *m_target;
|
||||
bool m_passSignal;
|
||||
};
|
||||
|
||||
// Used By ProxyFilter
|
||||
class OutputProxy : public CustomSignalPropagation<Sink>
|
||||
{
|
||||
public:
|
||||
OutputProxy(BufferedTransformation &owner, bool passSignal) : m_owner(owner), m_passSignal(passSignal) {}
|
||||
|
||||
bool GetPassSignal() const {return m_passSignal;}
|
||||
void SetPassSignal(bool passSignal) {m_passSignal = passSignal;}
|
||||
|
||||
unsigned int Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking)
|
||||
{return m_owner.AttachedTransformation()->Put2(begin, length, m_passSignal ? messageEnd : 0, blocking);}
|
||||
unsigned int PutModifiable2(byte *begin, unsigned int length, int messageEnd, bool blocking)
|
||||
{return m_owner.AttachedTransformation()->PutModifiable2(begin, length, m_passSignal ? messageEnd : 0, blocking);}
|
||||
void Initialize(const NameValuePairs ¶meters=g_nullNameValuePairs, int propagation=-1)
|
||||
{if (m_passSignal) m_owner.AttachedTransformation()->Initialize(parameters, propagation);}
|
||||
bool Flush(bool hardFlush, int propagation=-1, bool blocking=true)
|
||||
{return m_passSignal ? m_owner.AttachedTransformation()->Flush(hardFlush, propagation, blocking) : false;}
|
||||
bool MessageSeriesEnd(int propagation=-1, bool blocking=true)
|
||||
{return m_passSignal ? m_owner.AttachedTransformation()->MessageSeriesEnd(propagation, blocking) : false;}
|
||||
|
||||
unsigned int ChannelPut2(const std::string &channel, const byte *begin, unsigned int length, int messageEnd, bool blocking)
|
||||
{return m_owner.AttachedTransformation()->ChannelPut2(channel, begin, length, m_passSignal ? messageEnd : 0, blocking);}
|
||||
unsigned int ChannelPutModifiable2(const std::string &channel, byte *begin, unsigned int length, int messageEnd, bool blocking)
|
||||
{return m_owner.AttachedTransformation()->ChannelPutModifiable2(channel, begin, length, m_passSignal ? messageEnd : 0, blocking);}
|
||||
void ChannelInitialize(const std::string &channel, const NameValuePairs ¶meters, int propagation=-1)
|
||||
{if (m_passSignal) m_owner.AttachedTransformation()->ChannelInitialize(channel, parameters, propagation);}
|
||||
bool ChannelFlush(const std::string &channel, bool completeFlush, int propagation=-1, bool blocking=true)
|
||||
{return m_passSignal ? m_owner.AttachedTransformation()->ChannelFlush(channel, completeFlush, propagation, blocking) : false;}
|
||||
bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true)
|
||||
{return m_passSignal ? m_owner.AttachedTransformation()->ChannelMessageSeriesEnd(channel, propagation, blocking) : false;}
|
||||
|
||||
private:
|
||||
BufferedTransformation &m_owner;
|
||||
bool m_passSignal;
|
||||
};
|
||||
|
||||
//! Append input to a string object
|
||||
template <class T>
|
||||
class StringSinkTemplate : public Bufferless<Sink>
|
||||
{
|
||||
public:
|
||||
// VC60 workaround: no T::char_type
|
||||
typedef typename T::traits_type::char_type char_type;
|
||||
|
||||
StringSinkTemplate(T &output)
|
||||
: m_output(&output) {assert(sizeof(output[0])==1);}
|
||||
|
||||
void IsolatedInitialize(const NameValuePairs ¶meters)
|
||||
{if (!parameters.GetValue("OutputStringPointer", m_output)) throw InvalidArgument("StringSink: OutputStringPointer not specified");}
|
||||
|
||||
unsigned int Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking)
|
||||
{
|
||||
if (length > 0)
|
||||
{
|
||||
typename T::size_type size = m_output->size();
|
||||
if (length < size && size + length > m_output->capacity())
|
||||
m_output->reserve(2*size);
|
||||
m_output->append((const char_type *)begin, (const char_type *)begin+length);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
T *m_output;
|
||||
};
|
||||
|
||||
//! Append input to an std::string
|
||||
typedef StringSinkTemplate<std::string> StringSink;
|
||||
|
||||
//! Copy input to a memory buffer
|
||||
class ArraySink : public Bufferless<Sink>
|
||||
{
|
||||
public:
|
||||
ArraySink(const NameValuePairs ¶meters = g_nullNameValuePairs) {IsolatedInitialize(parameters);}
|
||||
ArraySink(byte *buf, unsigned int size) : m_buf(buf), m_size(size), m_total(0) {}
|
||||
|
||||
unsigned int AvailableSize() {return m_size - STDMIN(m_total, (unsigned long)m_size);}
|
||||
unsigned long TotalPutLength() {return m_total;}
|
||||
|
||||
void IsolatedInitialize(const NameValuePairs ¶meters);
|
||||
byte * CreatePutSpace(unsigned int &size);
|
||||
unsigned int Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking);
|
||||
|
||||
protected:
|
||||
byte *m_buf;
|
||||
unsigned int m_size;
|
||||
unsigned long m_total;
|
||||
};
|
||||
|
||||
//! Xor input to a memory buffer
|
||||
class ArrayXorSink : public ArraySink
|
||||
{
|
||||
public:
|
||||
ArrayXorSink(byte *buf, unsigned int size)
|
||||
: ArraySink(buf, size) {}
|
||||
|
||||
unsigned int Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking);
|
||||
byte * CreatePutSpace(unsigned int &size) {return BufferedTransformation::CreatePutSpace(size);}
|
||||
};
|
||||
|
||||
//! .
|
||||
class StringStore : public Store
|
||||
{
|
||||
public:
|
||||
StringStore(const char *string = NULL)
|
||||
{StoreInitialize(MakeParameters("InputBuffer", ConstByteArrayParameter(string)));}
|
||||
StringStore(const byte *string, unsigned int length)
|
||||
{StoreInitialize(MakeParameters("InputBuffer", ConstByteArrayParameter(string, length)));}
|
||||
template <class T> StringStore(const T &string)
|
||||
{StoreInitialize(MakeParameters("InputBuffer", ConstByteArrayParameter(string)));}
|
||||
|
||||
unsigned int TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel=NULL_CHANNEL, bool blocking=true);
|
||||
unsigned int CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end=ULONG_MAX, const std::string &channel=NULL_CHANNEL, bool blocking=true) const;
|
||||
|
||||
private:
|
||||
void StoreInitialize(const NameValuePairs ¶meters);
|
||||
|
||||
const byte *m_store;
|
||||
unsigned int m_length, m_count;
|
||||
};
|
||||
|
||||
//! A Filter that pumps data into its attachment as input
|
||||
class Source : public InputRejecting<Filter>
|
||||
{
|
||||
public:
|
||||
Source(BufferedTransformation *attachment)
|
||||
: InputRejecting<Filter>(attachment) {}
|
||||
|
||||
unsigned long Pump(unsigned long pumpMax=ULONG_MAX)
|
||||
{Pump2(pumpMax); return pumpMax;}
|
||||
unsigned int PumpMessages(unsigned int count=UINT_MAX)
|
||||
{PumpMessages2(count); return count;}
|
||||
void PumpAll()
|
||||
{PumpAll2();}
|
||||
virtual unsigned int Pump2(unsigned long &byteCount, bool blocking=true) =0;
|
||||
virtual unsigned int PumpMessages2(unsigned int &messageCount, bool blocking=true) =0;
|
||||
virtual unsigned int PumpAll2(bool blocking=true);
|
||||
virtual bool SourceExhausted() const =0;
|
||||
|
||||
protected:
|
||||
void SourceInitialize(bool pumpAll, const NameValuePairs ¶meters)
|
||||
{
|
||||
IsolatedInitialize(parameters);
|
||||
if (pumpAll)
|
||||
PumpAll();
|
||||
}
|
||||
};
|
||||
|
||||
//! Turn a Store into a Source
|
||||
template <class T>
|
||||
class SourceTemplate : public Source
|
||||
{
|
||||
public:
|
||||
SourceTemplate<T>(BufferedTransformation *attachment)
|
||||
: Source(attachment) {}
|
||||
SourceTemplate<T>(BufferedTransformation *attachment, T store)
|
||||
: Source(attachment), m_store(store) {}
|
||||
void IsolatedInitialize(const NameValuePairs ¶meters)
|
||||
{m_store.IsolatedInitialize(parameters);}
|
||||
unsigned int Pump2(unsigned long &byteCount, bool blocking=true)
|
||||
{return m_store.TransferTo2(*AttachedTransformation(), byteCount, NULL_CHANNEL, blocking);}
|
||||
unsigned int PumpMessages2(unsigned int &messageCount, bool blocking=true)
|
||||
{return m_store.TransferMessagesTo2(*AttachedTransformation(), messageCount, NULL_CHANNEL, blocking);}
|
||||
unsigned int PumpAll2(bool blocking=true)
|
||||
{return m_store.TransferAllTo2(*AttachedTransformation(), NULL_CHANNEL, blocking);}
|
||||
bool SourceExhausted() const
|
||||
{return !m_store.AnyRetrievable() && !m_store.AnyMessages();}
|
||||
void SetAutoSignalPropagation(int propagation)
|
||||
{m_store.SetAutoSignalPropagation(propagation);}
|
||||
int GetAutoSignalPropagation() const
|
||||
{return m_store.GetAutoSignalPropagation();}
|
||||
|
||||
protected:
|
||||
T m_store;
|
||||
};
|
||||
|
||||
//! .
|
||||
class StringSource : public SourceTemplate<StringStore>
|
||||
{
|
||||
public:
|
||||
StringSource(BufferedTransformation *attachment = NULL)
|
||||
: SourceTemplate<StringStore>(attachment) {}
|
||||
StringSource(const char *string, bool pumpAll, BufferedTransformation *attachment = NULL)
|
||||
: SourceTemplate<StringStore>(attachment) {SourceInitialize(pumpAll, MakeParameters("InputBuffer", ConstByteArrayParameter(string)));}
|
||||
StringSource(const byte *string, unsigned int length, bool pumpAll, BufferedTransformation *attachment = NULL)
|
||||
: SourceTemplate<StringStore>(attachment) {SourceInitialize(pumpAll, MakeParameters("InputBuffer", ConstByteArrayParameter(string, length)));}
|
||||
|
||||
#ifdef __MWERKS__ // CW60 workaround
|
||||
StringSource(const std::string &string, bool pumpAll, BufferedTransformation *attachment = NULL)
|
||||
#else
|
||||
template <class T> StringSource(const T &string, bool pumpAll, BufferedTransformation *attachment = NULL)
|
||||
#endif
|
||||
: SourceTemplate<StringStore>(attachment) {SourceInitialize(pumpAll, MakeParameters("InputBuffer", ConstByteArrayParameter(string)));}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,46 +0,0 @@
|
||||
#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) \
|
||||
{\
|
||||
case site: \
|
||||
if (Output(site, output, length, messageEnd, blocking)) \
|
||||
return STDMAX(1U, (unsigned int)length-m_inputPosition);\
|
||||
}
|
||||
|
||||
#define FILTER_OUTPUT_BYTE(site, output) \
|
||||
FILTER_OUTPUT(site, &(const byte &)(byte)output, 1, 0)
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,424 +0,0 @@
|
||||
#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 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;
|
||||
|
||||
//!
|
||||
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);
|
||||
|
||||
//@}
|
||||
|
||||
//! \name ACCESSORS
|
||||
//@{
|
||||
//! return true if *this can be represented as a signed long
|
||||
bool IsConvertableToLong() const;
|
||||
//! return equivalent signed long if possible, otherwise undefined
|
||||
signed long ConvertToLong() const;
|
||||
|
||||
//! number of significant bits = floor(log2(abs(*this))) + 1
|
||||
unsigned int BitCount() const;
|
||||
//! number of significant bytes = ceiling(BitCount()/8)
|
||||
unsigned int ByteCount() const;
|
||||
//! number of significant words = ceiling(ByteCount()/sizeof(word))
|
||||
unsigned int WordCount() const;
|
||||
|
||||
//! return the i-th bit, i=0 being the least significant bit
|
||||
bool GetBit(unsigned int i) const;
|
||||
//! return the i-th byte
|
||||
byte GetByte(unsigned int i) const;
|
||||
//! return n lowest bits of *this >> i
|
||||
unsigned long GetBits(unsigned int i, unsigned int n) const;
|
||||
|
||||
//!
|
||||
bool IsZero() const {return !*this;}
|
||||
//!
|
||||
bool NotZero() const {return !IsZero();}
|
||||
//!
|
||||
bool IsNegative() const {return sign == NEGATIVE;}
|
||||
//!
|
||||
bool NotNegative() const {return !IsNegative();}
|
||||
//!
|
||||
bool IsPositive() const {return NotNegative() && NotZero();}
|
||||
//!
|
||||
bool NotPositive() const {return !IsPositive();}
|
||||
//!
|
||||
bool IsEven() const {return GetBit(0) == 0;}
|
||||
//!
|
||||
bool IsOdd() const {return GetBit(0) == 1;}
|
||||
//@}
|
||||
|
||||
//! \name MANIPULATORS
|
||||
//@{
|
||||
//!
|
||||
Integer& operator=(const Integer& t);
|
||||
|
||||
//!
|
||||
Integer& operator+=(const Integer& t);
|
||||
//!
|
||||
Integer& operator-=(const Integer& t);
|
||||
//!
|
||||
Integer& operator*=(const Integer& t) {return *this = Times(t);}
|
||||
//!
|
||||
Integer& operator/=(const Integer& t) {return *this = DividedBy(t);}
|
||||
//!
|
||||
Integer& operator%=(const Integer& t) {return *this = Modulo(t);}
|
||||
//!
|
||||
Integer& operator/=(word t) {return *this = DividedBy(t);}
|
||||
//!
|
||||
Integer& operator%=(word t) {return *this = Modulo(t);}
|
||||
|
||||
//!
|
||||
Integer& operator<<=(unsigned int);
|
||||
//!
|
||||
Integer& operator>>=(unsigned int);
|
||||
|
||||
//!
|
||||
void Randomize(RandomNumberGenerator &rng, unsigned int bitcount);
|
||||
//!
|
||||
void Randomize(RandomNumberGenerator &rng, const Integer &min, const Integer &max);
|
||||
//! set this Integer to a random element of {x | min <= x <= max and x is of rnType and x % mod == equiv}
|
||||
/*! returns false if the set is empty */
|
||||
bool Randomize(RandomNumberGenerator &rng, const Integer &min, const Integer &max, RandomNumberType rnType, const Integer &equiv=Zero(), const Integer &mod=One());
|
||||
|
||||
bool GenerateRandomNoThrow(RandomNumberGenerator &rng, const NameValuePairs ¶ms = g_nullNameValuePairs);
|
||||
void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs ¶ms = g_nullNameValuePairs)
|
||||
{
|
||||
if (!GenerateRandomNoThrow(rng, params))
|
||||
throw RandomNumberNotFound();
|
||||
}
|
||||
|
||||
//! set the n-th bit to value
|
||||
void SetBit(unsigned int n, bool value=1);
|
||||
//! set the n-th byte to value
|
||||
void SetByte(unsigned int n, byte value);
|
||||
|
||||
//!
|
||||
void Negate();
|
||||
//!
|
||||
void SetPositive() {sign = POSITIVE;}
|
||||
//!
|
||||
void SetNegative() {if (!!(*this)) sign = NEGATIVE;}
|
||||
|
||||
//!
|
||||
void swap(Integer &a);
|
||||
//@}
|
||||
|
||||
//! \name UNARY OPERATORS
|
||||
//@{
|
||||
//!
|
||||
bool operator!() const;
|
||||
//!
|
||||
Integer operator+() const {return *this;}
|
||||
//!
|
||||
Integer operator-() const;
|
||||
//!
|
||||
Integer& operator++();
|
||||
//!
|
||||
Integer& operator--();
|
||||
//!
|
||||
Integer operator++(int) {Integer temp = *this; ++*this; return temp;}
|
||||
//!
|
||||
Integer operator--(int) {Integer temp = *this; --*this; return temp;}
|
||||
//@}
|
||||
|
||||
//! \name BINARY OPERATORS
|
||||
//@{
|
||||
//! signed comparison
|
||||
/*! \retval -1 if *this < a
|
||||
\retval 0 if *this = a
|
||||
\retval 1 if *this > a
|
||||
*/
|
||||
int Compare(const Integer& a) const;
|
||||
|
||||
//!
|
||||
Integer Plus(const Integer &b) const;
|
||||
//!
|
||||
Integer Minus(const Integer &b) const;
|
||||
//!
|
||||
Integer Times(const Integer &b) const;
|
||||
//!
|
||||
Integer DividedBy(const Integer &b) const;
|
||||
//!
|
||||
Integer Modulo(const Integer &b) const;
|
||||
//!
|
||||
Integer DividedBy(word b) const;
|
||||
//!
|
||||
word Modulo(word b) const;
|
||||
|
||||
//!
|
||||
Integer operator>>(unsigned int n) const {return Integer(*this)>>=n;}
|
||||
//!
|
||||
Integer operator<<(unsigned int n) const {return Integer(*this)<<=n;}
|
||||
//@}
|
||||
|
||||
//! \name OTHER ARITHMETIC FUNCTIONS
|
||||
//@{
|
||||
//!
|
||||
Integer AbsoluteValue() const;
|
||||
//!
|
||||
Integer Doubled() const {return Plus(*this);}
|
||||
//!
|
||||
Integer Squared() const {return Times(*this);}
|
||||
//! extract square root, if negative return 0, else return floor of square root
|
||||
Integer SquareRoot() const;
|
||||
//! return whether this integer is a perfect square
|
||||
bool IsSquare() const;
|
||||
|
||||
//! is 1 or -1
|
||||
bool IsUnit() const;
|
||||
//! return inverse if 1 or -1, otherwise return 0
|
||||
Integer MultiplicativeInverse() const;
|
||||
|
||||
//! modular multiplication
|
||||
friend Integer a_times_b_mod_c(const Integer &x, const Integer& y, const Integer& m);
|
||||
//! modular exponentiation
|
||||
friend Integer a_exp_b_mod_c(const Integer &x, const Integer& e, const Integer& m);
|
||||
|
||||
//! calculate r and q such that (a == d*q + r) && (0 <= r < abs(d))
|
||||
static void Divide(Integer &r, Integer &q, const Integer &a, const Integer &d);
|
||||
//! use a faster division algorithm when divisor is short
|
||||
static void Divide(word &r, Integer &q, const Integer &a, word d);
|
||||
|
||||
//! returns same result as Divide(r, q, a, Power2(n)), but faster
|
||||
static void DivideByPowerOf2(Integer &r, Integer &q, const Integer &a, unsigned int n);
|
||||
|
||||
//! greatest common divisor
|
||||
static Integer Gcd(const Integer &a, const Integer &n);
|
||||
//! calculate multiplicative inverse of *this mod n
|
||||
Integer InverseMod(const Integer &n) const;
|
||||
//!
|
||||
word InverseMod(word n) const;
|
||||
//@}
|
||||
|
||||
//! \name INPUT/OUTPUT
|
||||
//@{
|
||||
//!
|
||||
friend std::istream& operator>>(std::istream& in, Integer &a);
|
||||
//!
|
||||
friend std::ostream& operator<<(std::ostream& out, const Integer &a);
|
||||
//@}
|
||||
|
||||
private:
|
||||
friend class ModularArithmetic;
|
||||
friend class MontgomeryRepresentation;
|
||||
friend class HalfMontgomeryRepresentation;
|
||||
|
||||
Integer(word value, unsigned int length);
|
||||
|
||||
int PositiveCompare(const Integer &t) const;
|
||||
friend void PositiveAdd(Integer &sum, const Integer &a, const Integer &b);
|
||||
friend void PositiveSubtract(Integer &diff, const Integer &a, const Integer &b);
|
||||
friend void PositiveMultiply(Integer &product, const Integer &a, const Integer &b);
|
||||
friend void PositiveDivide(Integer &remainder, Integer "ient, const Integer ÷nd, const Integer &divisor);
|
||||
|
||||
SecAlignedWordBlock reg;
|
||||
Sign sign;
|
||||
};
|
||||
|
||||
//!
|
||||
inline bool operator==(const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)==0;}
|
||||
//!
|
||||
inline bool operator!=(const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)!=0;}
|
||||
//!
|
||||
inline bool operator> (const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)> 0;}
|
||||
//!
|
||||
inline bool operator>=(const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)>=0;}
|
||||
//!
|
||||
inline bool operator< (const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)< 0;}
|
||||
//!
|
||||
inline bool operator<=(const CryptoPP::Integer& a, const CryptoPP::Integer& b) {return a.Compare(b)<=0;}
|
||||
//!
|
||||
inline CryptoPP::Integer operator+(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.Plus(b);}
|
||||
//!
|
||||
inline CryptoPP::Integer operator-(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.Minus(b);}
|
||||
//!
|
||||
inline CryptoPP::Integer operator*(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.Times(b);}
|
||||
//!
|
||||
inline CryptoPP::Integer operator/(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.DividedBy(b);}
|
||||
//!
|
||||
inline CryptoPP::Integer operator%(const CryptoPP::Integer &a, const CryptoPP::Integer &b) {return a.Modulo(b);}
|
||||
//!
|
||||
inline CryptoPP::Integer operator/(const CryptoPP::Integer &a, CryptoPP::word b) {return a.DividedBy(b);}
|
||||
//!
|
||||
inline CryptoPP::word operator%(const CryptoPP::Integer &a, CryptoPP::word b) {return a.Modulo(b);}
|
||||
|
||||
}
|
||||
|
||||
NAMESPACE_BEGIN(std)
|
||||
template<> inline void swap(CryptoPP::Integer &a, CryptoPP::Integer &b)
|
||||
{
|
||||
a.swap(b);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,124 +0,0 @@
|
||||
// iterhash.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "global.h"
|
||||
#include "pch.h"
|
||||
#include "iterhash.h"
|
||||
#include "misc.h"
|
||||
|
||||
namespace 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_countLo(0), m_countHi(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>;
|
||||
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
#ifndef CRYPTOPP_ITERHASH_H
|
||||
#define CRYPTOPP_ITERHASH_H
|
||||
|
||||
#include "cryptlib.h"
|
||||
#include "secblock.h"
|
||||
#include "misc.h"
|
||||
|
||||
namespace 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(this->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)
|
||||
{
|
||||
this->ThrowIfInvalidTruncatedSize(size);
|
||||
|
||||
PadLastBlock(this->BlockSize() - 2*sizeof(HashWordType));
|
||||
CorrectEndianess(this->m_data, this->m_data, this->BlockSize() - 2*sizeof(HashWordType));
|
||||
|
||||
this->m_data[this->m_data.size()-2] = B::ToEnum() ? this->GetBitCountHi() : this->GetBitCountLo();
|
||||
this->m_data[this->m_data.size()-1] = B::ToEnum() ? this->GetBitCountLo() : this->GetBitCountHi();
|
||||
|
||||
vTransform(this->m_data);
|
||||
CorrectEndianess(this->m_digest, this->m_digest, this->DigestSize());
|
||||
memcpy(hash, this->m_digest, size);
|
||||
|
||||
this->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(this->m_data.begin(), input, this->BlockSize());
|
||||
vTransform(this->m_data);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,84 +0,0 @@
|
||||
// misc.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "global.h"
|
||||
#include "pch.h"
|
||||
#include "misc.h"
|
||||
#include "words.h"
|
||||
|
||||
namespace 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 (((uintptr_t)buf | (uintptr_t)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 (((uintptr_t)output | (uintptr_t)input | (uintptr_t)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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,525 +0,0 @@
|
||||
#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 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((uintptr_t)p, alignment) == 0 : (uintptr_t)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
|
||||
#if !defined(__MWERKS__)
|
||||
# include <ppc_intrinsics.h>
|
||||
#endif
|
||||
|
||||
template<> inline word32 rotlFixed<word32>(word32 x, const unsigned int y) __attribute__((always_inline));
|
||||
template<> inline word32 rotlFixed<word32>(word32 x, const unsigned int y)
|
||||
{
|
||||
assert(y < 32);
|
||||
return y ? __rlwinm(x,y,0,31) : x;
|
||||
}
|
||||
|
||||
template<> inline word32 rotrFixed<word32>(word32 x, const unsigned int y) __attribute__((always_inline));
|
||||
template<> inline word32 rotrFixed<word32>(word32 x, const 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
|
||||
|
||||
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 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 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);
|
||||
}
|
||||
|
||||
// ************** 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // MISC_H
|
||||
@@ -1,150 +0,0 @@
|
||||
#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 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)
|
||||
: AbstractRing<Integer>(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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,72 +0,0 @@
|
||||
// mqueue.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "global.h"
|
||||
#include "pch.h"
|
||||
#include "mqueue.h"
|
||||
|
||||
namespace 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;
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
#ifndef CRYPTOPP_MQUEUE_H
|
||||
#define CRYPTOPP_MQUEUE_H
|
||||
|
||||
#include "queue.h"
|
||||
#include "filters.h"
|
||||
#include <deque>
|
||||
|
||||
namespace CryptoPP {
|
||||
|
||||
//! Message Queue
|
||||
class MessageQueue : public AutoSignaling<BufferedTransformation>
|
||||
{
|
||||
public:
|
||||
MessageQueue(unsigned int nodeSize=256);
|
||||
|
||||
void IsolatedInitialize(const NameValuePairs ¶meters)
|
||||
{m_queue.IsolatedInitialize(parameters); m_lengths.assign(1, 0U); m_messageCounts.assign(1, 0U);}
|
||||
unsigned int Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking)
|
||||
{
|
||||
m_queue.Put(begin, length);
|
||||
m_lengths.back() += length;
|
||||
if (messageEnd)
|
||||
{
|
||||
m_lengths.push_back(0);
|
||||
m_messageCounts.back()++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
bool IsolatedFlush(bool hardFlush, bool blocking) {return false;}
|
||||
bool IsolatedMessageSeriesEnd(bool blocking)
|
||||
{m_messageCounts.push_back(0); return false;}
|
||||
|
||||
unsigned long MaxRetrievable() const
|
||||
{return m_lengths.front();}
|
||||
bool AnyRetrievable() const
|
||||
{return m_lengths.front() > 0;}
|
||||
|
||||
unsigned int TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel=NULL_CHANNEL, bool blocking=true);
|
||||
unsigned int CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end=ULONG_MAX, const std::string &channel=NULL_CHANNEL, bool blocking=true) const;
|
||||
|
||||
unsigned long TotalBytesRetrievable() const
|
||||
{return m_queue.MaxRetrievable();}
|
||||
unsigned int NumberOfMessages() const
|
||||
{return m_lengths.size()-1;}
|
||||
bool GetNextMessage();
|
||||
|
||||
unsigned int NumberOfMessagesInThisSeries() const
|
||||
{return m_messageCounts[0];}
|
||||
unsigned int NumberOfMessageSeries() const
|
||||
{return m_messageCounts.size()-1;}
|
||||
|
||||
unsigned int CopyMessagesTo(BufferedTransformation &target, unsigned int count=UINT_MAX, const std::string &channel=NULL_CHANNEL) const;
|
||||
|
||||
const byte * Spy(unsigned int &contiguousSize) const;
|
||||
|
||||
void swap(MessageQueue &rhs);
|
||||
|
||||
private:
|
||||
ByteQueue m_queue;
|
||||
std::deque<unsigned long> m_lengths, m_messageCounts;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
NAMESPACE_BEGIN(std)
|
||||
template<> inline void swap(CryptoPP::MessageQueue &a, CryptoPP::MessageQueue &b)
|
||||
{
|
||||
a.swap(b);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,734 +0,0 @@
|
||||
// nbtheory.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "global.h"
|
||||
#include "pch.h"
|
||||
#include "nbtheory.h"
|
||||
#include "modarith.h"
|
||||
#include "algparam.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <vector>
|
||||
|
||||
namespace CryptoPP {
|
||||
|
||||
const unsigned int maxPrimeTableSize = 3511; // last prime 32719
|
||||
const word lastSmallPrime = 32719;
|
||||
unsigned int primeTableSize=552;
|
||||
|
||||
word primeTable[maxPrimeTableSize] =
|
||||
{2, 3, 5, 7, 11, 13, 17, 19,
|
||||
23, 29, 31, 37, 41, 43, 47, 53,
|
||||
59, 61, 67, 71, 73, 79, 83, 89,
|
||||
97, 101, 103, 107, 109, 113, 127, 131,
|
||||
137, 139, 149, 151, 157, 163, 167, 173,
|
||||
179, 181, 191, 193, 197, 199, 211, 223,
|
||||
227, 229, 233, 239, 241, 251, 257, 263,
|
||||
269, 271, 277, 281, 283, 293, 307, 311,
|
||||
313, 317, 331, 337, 347, 349, 353, 359,
|
||||
367, 373, 379, 383, 389, 397, 401, 409,
|
||||
419, 421, 431, 433, 439, 443, 449, 457,
|
||||
461, 463, 467, 479, 487, 491, 499, 503,
|
||||
509, 521, 523, 541, 547, 557, 563, 569,
|
||||
571, 577, 587, 593, 599, 601, 607, 613,
|
||||
617, 619, 631, 641, 643, 647, 653, 659,
|
||||
661, 673, 677, 683, 691, 701, 709, 719,
|
||||
727, 733, 739, 743, 751, 757, 761, 769,
|
||||
773, 787, 797, 809, 811, 821, 823, 827,
|
||||
829, 839, 853, 857, 859, 863, 877, 881,
|
||||
883, 887, 907, 911, 919, 929, 937, 941,
|
||||
947, 953, 967, 971, 977, 983, 991, 997,
|
||||
1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049,
|
||||
1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097,
|
||||
1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163,
|
||||
1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223,
|
||||
1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283,
|
||||
1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321,
|
||||
1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423,
|
||||
1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459,
|
||||
1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511,
|
||||
1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571,
|
||||
1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619,
|
||||
1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693,
|
||||
1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747,
|
||||
1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811,
|
||||
1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877,
|
||||
1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949,
|
||||
1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003,
|
||||
2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069,
|
||||
2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129,
|
||||
2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203,
|
||||
2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267,
|
||||
2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311,
|
||||
2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377,
|
||||
2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423,
|
||||
2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503,
|
||||
2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579,
|
||||
2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657,
|
||||
2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693,
|
||||
2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741,
|
||||
2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801,
|
||||
2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861,
|
||||
2879, 2887, 2897, 2903, 2909, 2917, 2927, 2939,
|
||||
2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011,
|
||||
3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079,
|
||||
3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167,
|
||||
3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221,
|
||||
3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301,
|
||||
3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347,
|
||||
3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413,
|
||||
3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491,
|
||||
3499, 3511, 3517, 3527, 3529, 3533, 3539, 3541,
|
||||
3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607,
|
||||
3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671,
|
||||
3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727,
|
||||
3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797,
|
||||
3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863,
|
||||
3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923,
|
||||
3929, 3931, 3943, 3947, 3967, 3989, 4001, 4003};
|
||||
|
||||
void BuildPrimeTable()
|
||||
{
|
||||
unsigned int p=primeTable[primeTableSize-1];
|
||||
for (unsigned int i=primeTableSize; i<maxPrimeTableSize; i++)
|
||||
{
|
||||
int j;
|
||||
do
|
||||
{
|
||||
p+=2;
|
||||
for (j=1; j<54; j++)
|
||||
if (p%primeTable[j] == 0)
|
||||
break;
|
||||
} while (j!=54);
|
||||
primeTable[i] = p;
|
||||
}
|
||||
primeTableSize = maxPrimeTableSize;
|
||||
assert(primeTable[primeTableSize-1] == lastSmallPrime);
|
||||
}
|
||||
|
||||
bool IsSmallPrime(const Integer &p)
|
||||
{
|
||||
BuildPrimeTable();
|
||||
|
||||
if (p.IsPositive() && p <= primeTable[primeTableSize-1])
|
||||
return std::binary_search(primeTable, primeTable+primeTableSize, (word)p.ConvertToLong());
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TrialDivision(const Integer &p, unsigned bound)
|
||||
{
|
||||
assert(primeTable[primeTableSize-1] >= bound);
|
||||
|
||||
unsigned int i;
|
||||
for (i = 0; primeTable[i]<bound; i++)
|
||||
if ((p % primeTable[i]) == 0)
|
||||
return true;
|
||||
|
||||
if (bound == primeTable[i])
|
||||
return (p % bound == 0);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SmallDivisorsTest(const Integer &p)
|
||||
{
|
||||
BuildPrimeTable();
|
||||
return !TrialDivision(p, primeTable[primeTableSize-1]);
|
||||
}
|
||||
|
||||
bool IsStrongProbablePrime(const Integer &n, const Integer &b)
|
||||
{
|
||||
if (n <= 3)
|
||||
return n==2 || n==3;
|
||||
|
||||
assert(n>3 && b>1 && b<n-1);
|
||||
|
||||
if ((n.IsEven() && n!=2) || GCD(b, n) != 1)
|
||||
return false;
|
||||
|
||||
Integer nminus1 = (n-1);
|
||||
unsigned int a;
|
||||
|
||||
// calculate a = largest power of 2 that divides (n-1)
|
||||
for (a=0; ; a++)
|
||||
if (nminus1.GetBit(a))
|
||||
break;
|
||||
Integer m = nminus1>>a;
|
||||
|
||||
Integer z = a_exp_b_mod_c(b, m, n);
|
||||
if (z==1 || z==nminus1)
|
||||
return true;
|
||||
for (unsigned j=1; j<a; j++)
|
||||
{
|
||||
z = z.Squared()%n;
|
||||
if (z==nminus1)
|
||||
return true;
|
||||
if (z==1)
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RabinMillerTest(RandomNumberGenerator &rng, const Integer &n, unsigned int rounds)
|
||||
{
|
||||
if (n <= 3)
|
||||
return n==2 || n==3;
|
||||
|
||||
assert(n>3);
|
||||
|
||||
Integer b;
|
||||
for (unsigned int i=0; i<rounds; i++)
|
||||
{
|
||||
b.Randomize(rng, 2, n-2);
|
||||
if (!IsStrongProbablePrime(n, b))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool IsStrongLucasProbablePrime(const Integer &n)
|
||||
{
|
||||
if (n <= 1)
|
||||
return false;
|
||||
|
||||
if (n.IsEven())
|
||||
return n==2;
|
||||
|
||||
assert(n>2);
|
||||
|
||||
Integer b=3;
|
||||
unsigned int i=0;
|
||||
int j;
|
||||
|
||||
while ((j=Jacobi(b.Squared()-4, n)) == 1)
|
||||
{
|
||||
if (++i==64 && n.IsSquare()) // avoid infinite loop if n is a square
|
||||
return false;
|
||||
++b; ++b;
|
||||
}
|
||||
|
||||
if (j==0)
|
||||
return false;
|
||||
|
||||
Integer n1 = n+1;
|
||||
unsigned int a;
|
||||
|
||||
// calculate a = largest power of 2 that divides n1
|
||||
for (a=0; ; a++)
|
||||
if (n1.GetBit(a))
|
||||
break;
|
||||
Integer m = n1>>a;
|
||||
|
||||
Integer z = Lucas(m, b, n);
|
||||
if (z==2 || z==n-2)
|
||||
return true;
|
||||
for (i=1; i<a; i++)
|
||||
{
|
||||
z = (z.Squared()-2)%n;
|
||||
if (z==n-2)
|
||||
return true;
|
||||
if (z==2)
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsPrime(const Integer &p)
|
||||
{
|
||||
static const Integer lastSmallPrimeSquared = Integer(lastSmallPrime).Squared();
|
||||
|
||||
if (p <= lastSmallPrime)
|
||||
return IsSmallPrime(p);
|
||||
else if (p <= lastSmallPrimeSquared)
|
||||
return SmallDivisorsTest(p);
|
||||
else
|
||||
return SmallDivisorsTest(p) && IsStrongProbablePrime(p, 3) && IsStrongLucasProbablePrime(p);
|
||||
}
|
||||
|
||||
bool VerifyPrime(RandomNumberGenerator &rng, const Integer &p, unsigned int level)
|
||||
{
|
||||
bool pass = IsPrime(p) && RabinMillerTest(rng, p, 1);
|
||||
if (level >= 1)
|
||||
pass = pass && RabinMillerTest(rng, p, 10);
|
||||
return pass;
|
||||
}
|
||||
|
||||
unsigned int PrimeSearchInterval(const Integer &max)
|
||||
{
|
||||
return max.BitCount();
|
||||
}
|
||||
|
||||
static inline bool FastProbablePrimeTest(const Integer &n)
|
||||
{
|
||||
return IsStrongProbablePrime(n,2);
|
||||
}
|
||||
|
||||
AlgorithmParameters<AlgorithmParameters<AlgorithmParameters<NullNameValuePairs, Integer::RandomNumberType>, Integer>, Integer>
|
||||
MakeParametersForTwoPrimesOfEqualSize(unsigned int productBitLength)
|
||||
{
|
||||
if (productBitLength < 16)
|
||||
throw InvalidArgument("invalid bit length");
|
||||
|
||||
Integer minP, maxP;
|
||||
|
||||
if (productBitLength%2==0)
|
||||
{
|
||||
minP = Integer(182) << (productBitLength/2-8);
|
||||
maxP = Integer::Power2(productBitLength/2)-1;
|
||||
}
|
||||
else
|
||||
{
|
||||
minP = Integer::Power2((productBitLength-1)/2);
|
||||
maxP = Integer(181) << ((productBitLength+1)/2-8);
|
||||
}
|
||||
|
||||
return MakeParameters("RandomNumberType", Integer::PRIME)("Min", minP)("Max", maxP);
|
||||
}
|
||||
|
||||
class PrimeSieve
|
||||
{
|
||||
public:
|
||||
// delta == 1 or -1 means double sieve with p = 2*q + delta
|
||||
PrimeSieve(const Integer &first, const Integer &last, const Integer &step, signed int delta=0);
|
||||
bool NextCandidate(Integer &c);
|
||||
|
||||
void DoSieve();
|
||||
static void SieveSingle(std::vector<bool> &sieve, word p, const Integer &first, const Integer &step, word stepInv);
|
||||
|
||||
Integer m_first, m_last, m_step;
|
||||
signed int m_delta;
|
||||
word m_next;
|
||||
std::vector<bool> m_sieve;
|
||||
};
|
||||
|
||||
PrimeSieve::PrimeSieve(const Integer &first, const Integer &last, const Integer &step, signed int delta)
|
||||
: m_first(first), m_last(last), m_step(step), m_delta(delta), m_next(0)
|
||||
{
|
||||
DoSieve();
|
||||
}
|
||||
|
||||
bool PrimeSieve::NextCandidate(Integer &c)
|
||||
{
|
||||
m_next = std::find(m_sieve.begin()+m_next, m_sieve.end(), false) - m_sieve.begin();
|
||||
if (m_next == m_sieve.size())
|
||||
{
|
||||
m_first += m_sieve.size()*m_step;
|
||||
if (m_first > m_last)
|
||||
return false;
|
||||
else
|
||||
{
|
||||
m_next = 0;
|
||||
DoSieve();
|
||||
return NextCandidate(c);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
c = m_first + m_next*m_step;
|
||||
++m_next;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void PrimeSieve::SieveSingle(std::vector<bool> &sieve, word p, const Integer &first, const Integer &step, word stepInv)
|
||||
{
|
||||
if (stepInv)
|
||||
{
|
||||
unsigned int sieveSize = sieve.size();
|
||||
word j = word((dword(p-(first%p))*stepInv) % p);
|
||||
// if the first multiple of p is p, skip it
|
||||
if (first.WordCount() <= 1 && first + step*j == p)
|
||||
j += p;
|
||||
for (; j < sieveSize; j += p)
|
||||
sieve[j] = true;
|
||||
}
|
||||
}
|
||||
|
||||
void PrimeSieve::DoSieve()
|
||||
{
|
||||
BuildPrimeTable();
|
||||
|
||||
const unsigned int maxSieveSize = 32768;
|
||||
unsigned int sieveSize = STDMIN(Integer(maxSieveSize), (m_last-m_first)/m_step+1).ConvertToLong();
|
||||
|
||||
m_sieve.clear();
|
||||
m_sieve.resize(sieveSize, false);
|
||||
|
||||
if (m_delta == 0)
|
||||
{
|
||||
for (unsigned int i = 0; i < primeTableSize; ++i)
|
||||
SieveSingle(m_sieve, primeTable[i], m_first, m_step, m_step.InverseMod(primeTable[i]));
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(m_step%2==0);
|
||||
Integer qFirst = (m_first-m_delta) >> 1;
|
||||
Integer halfStep = m_step >> 1;
|
||||
for (unsigned int i = 0; i < primeTableSize; ++i)
|
||||
{
|
||||
word p = primeTable[i];
|
||||
word stepInv = m_step.InverseMod(p);
|
||||
SieveSingle(m_sieve, p, m_first, m_step, stepInv);
|
||||
|
||||
word halfStepInv = 2*stepInv < p ? 2*stepInv : 2*stepInv-p;
|
||||
SieveSingle(m_sieve, p, qFirst, halfStep, halfStepInv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool FirstPrime(Integer &p, const Integer &max, const Integer &equiv, const Integer &mod, const PrimeSelector *pSelector)
|
||||
{
|
||||
assert(!equiv.IsNegative() && equiv < mod);
|
||||
|
||||
Integer gcd = GCD(equiv, mod);
|
||||
if (gcd != Integer::One())
|
||||
{
|
||||
// the only possible prime p such that p%mod==equiv where GCD(mod,equiv)!=1 is GCD(mod,equiv)
|
||||
if (p <= gcd && gcd <= max && IsPrime(gcd))
|
||||
{
|
||||
p = gcd;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
BuildPrimeTable();
|
||||
|
||||
if (p <= primeTable[primeTableSize-1])
|
||||
{
|
||||
word *pItr;
|
||||
|
||||
--p;
|
||||
if (p.IsPositive())
|
||||
pItr = std::upper_bound(primeTable, primeTable+primeTableSize, (word)p.ConvertToLong());
|
||||
else
|
||||
pItr = primeTable;
|
||||
|
||||
while (pItr < primeTable+primeTableSize && *pItr%mod != equiv)
|
||||
++pItr;
|
||||
|
||||
if (pItr < primeTable+primeTableSize)
|
||||
{
|
||||
p = *pItr;
|
||||
return p <= max;
|
||||
}
|
||||
|
||||
p = primeTable[primeTableSize-1]+1;
|
||||
}
|
||||
|
||||
assert(p > primeTable[primeTableSize-1]);
|
||||
|
||||
if (mod.IsOdd())
|
||||
return FirstPrime(p, max, CRT(equiv, mod, 1, 2, 1), mod<<1, pSelector);
|
||||
|
||||
p += (equiv-p)%mod;
|
||||
|
||||
if (p>max)
|
||||
return false;
|
||||
|
||||
PrimeSieve sieve(p, max, mod);
|
||||
|
||||
while (sieve.NextCandidate(p))
|
||||
{
|
||||
if ((!pSelector || pSelector->IsAcceptable(p)) && FastProbablePrimeTest(p) && IsPrime(p))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Integer CRT(const Integer &xp, const Integer &p, const Integer &xq, const Integer &q, const Integer &u)
|
||||
{
|
||||
// isn't operator overloading great?
|
||||
return p * (u * (xq-xp) % q) + xp;
|
||||
}
|
||||
|
||||
Integer CRT(const Integer &xp, const Integer &p, const Integer &xq, const Integer &q)
|
||||
{
|
||||
return CRT(xp, p, xq, q, EuclideanMultiplicativeInverse(p, q));
|
||||
}
|
||||
|
||||
Integer ModularSquareRoot(const Integer &a, const Integer &p)
|
||||
{
|
||||
if (p%4 == 3)
|
||||
return a_exp_b_mod_c(a, (p+1)/4, p);
|
||||
|
||||
Integer q=p-1;
|
||||
unsigned int r=0;
|
||||
while (q.IsEven())
|
||||
{
|
||||
r++;
|
||||
q >>= 1;
|
||||
}
|
||||
|
||||
Integer n=2;
|
||||
while (Jacobi(n, p) != -1)
|
||||
++n;
|
||||
|
||||
Integer y = a_exp_b_mod_c(n, q, p);
|
||||
Integer x = a_exp_b_mod_c(a, (q-1)/2, p);
|
||||
Integer b = (x.Squared()%p)*a%p;
|
||||
x = a*x%p;
|
||||
Integer tempb, t;
|
||||
|
||||
while (b != 1)
|
||||
{
|
||||
unsigned m=0;
|
||||
tempb = b;
|
||||
do
|
||||
{
|
||||
m++;
|
||||
b = b.Squared()%p;
|
||||
if (m==r)
|
||||
return Integer::Zero();
|
||||
}
|
||||
while (b != 1);
|
||||
|
||||
t = y;
|
||||
for (unsigned i=0; i<r-m-1; i++)
|
||||
t = t.Squared()%p;
|
||||
y = t.Squared()%p;
|
||||
r = m;
|
||||
x = x*t%p;
|
||||
b = tempb*y%p;
|
||||
}
|
||||
|
||||
assert(x.Squared()%p == a);
|
||||
return x;
|
||||
}
|
||||
|
||||
bool SolveModularQuadraticEquation(Integer &r1, Integer &r2, const Integer &a, const Integer &b, const Integer &c, const Integer &p)
|
||||
{
|
||||
Integer D = (b.Squared() - 4*a*c) % p;
|
||||
switch (Jacobi(D, p))
|
||||
{
|
||||
default:
|
||||
assert(false); // not reached
|
||||
return false;
|
||||
case -1:
|
||||
return false;
|
||||
case 0:
|
||||
r1 = r2 = (-b*(a+a).InverseMod(p)) % p;
|
||||
assert(((r1.Squared()*a + r1*b + c) % p).IsZero());
|
||||
return true;
|
||||
case 1:
|
||||
Integer s = ModularSquareRoot(D, p);
|
||||
Integer t = (a+a).InverseMod(p);
|
||||
r1 = (s-b)*t % p;
|
||||
r2 = (-s-b)*t % p;
|
||||
assert(((r1.Squared()*a + r1*b + c) % p).IsZero());
|
||||
assert(((r2.Squared()*a + r2*b + c) % p).IsZero());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Integer ModularRoot(const Integer &a, const Integer &dp, const Integer &dq,
|
||||
const Integer &p, const Integer &q, const Integer &u)
|
||||
{
|
||||
Integer p2 = ModularExponentiation((a % p), dp, p);
|
||||
Integer q2 = ModularExponentiation((a % q), dq, q);
|
||||
return CRT(p2, p, q2, q, u);
|
||||
}
|
||||
|
||||
Integer ModularRoot(const Integer &a, const Integer &e,
|
||||
const Integer &p, const Integer &q)
|
||||
{
|
||||
Integer dp = EuclideanMultiplicativeInverse(e, p-1);
|
||||
Integer dq = EuclideanMultiplicativeInverse(e, q-1);
|
||||
Integer u = EuclideanMultiplicativeInverse(p, q);
|
||||
assert(!!dp && !!dq && !!u);
|
||||
return ModularRoot(a, dp, dq, p, q, u);
|
||||
}
|
||||
|
||||
/*
|
||||
Integer GCDI(const Integer &x, const Integer &y)
|
||||
{
|
||||
Integer a=x, b=y;
|
||||
unsigned k=0;
|
||||
|
||||
assert(!!a && !!b);
|
||||
|
||||
while (a[0]==0 && b[0]==0)
|
||||
{
|
||||
a >>= 1;
|
||||
b >>= 1;
|
||||
k++;
|
||||
}
|
||||
|
||||
while (a[0]==0)
|
||||
a >>= 1;
|
||||
|
||||
while (b[0]==0)
|
||||
b >>= 1;
|
||||
|
||||
while (1)
|
||||
{
|
||||
switch (a.Compare(b))
|
||||
{
|
||||
case -1:
|
||||
b -= a;
|
||||
while (b[0]==0)
|
||||
b >>= 1;
|
||||
break;
|
||||
|
||||
case 0:
|
||||
return (a <<= k);
|
||||
|
||||
case 1:
|
||||
a -= b;
|
||||
while (a[0]==0)
|
||||
a >>= 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Integer EuclideanMultiplicativeInverse(const Integer &a, const Integer &b)
|
||||
{
|
||||
assert(b.Positive());
|
||||
|
||||
if (a.Negative())
|
||||
return EuclideanMultiplicativeInverse(a%b, b);
|
||||
|
||||
if (b[0]==0)
|
||||
{
|
||||
if (!b || a[0]==0)
|
||||
return Integer::Zero(); // no inverse
|
||||
if (a==1)
|
||||
return 1;
|
||||
Integer u = EuclideanMultiplicativeInverse(b, a);
|
||||
if (!u)
|
||||
return Integer::Zero(); // no inverse
|
||||
else
|
||||
return (b*(a-u)+1)/a;
|
||||
}
|
||||
|
||||
Integer u=1, d=a, v1=b, v3=b, t1, t3, b2=(b+1)>>1;
|
||||
|
||||
if (a[0])
|
||||
{
|
||||
t1 = Integer::Zero();
|
||||
t3 = -b;
|
||||
}
|
||||
else
|
||||
{
|
||||
t1 = b2;
|
||||
t3 = a>>1;
|
||||
}
|
||||
|
||||
while (!!t3)
|
||||
{
|
||||
while (t3[0]==0)
|
||||
{
|
||||
t3 >>= 1;
|
||||
if (t1[0]==0)
|
||||
t1 >>= 1;
|
||||
else
|
||||
{
|
||||
t1 >>= 1;
|
||||
t1 += b2;
|
||||
}
|
||||
}
|
||||
if (t3.Positive())
|
||||
{
|
||||
u = t1;
|
||||
d = t3;
|
||||
}
|
||||
else
|
||||
{
|
||||
v1 = b-t1;
|
||||
v3 = -t3;
|
||||
}
|
||||
t1 = u-v1;
|
||||
t3 = d-v3;
|
||||
if (t1.Negative())
|
||||
t1 += b;
|
||||
}
|
||||
if (d==1)
|
||||
return u;
|
||||
else
|
||||
return Integer::Zero(); // no inverse
|
||||
}
|
||||
*/
|
||||
|
||||
int Jacobi(const Integer &aIn, const Integer &bIn)
|
||||
{
|
||||
assert(bIn.IsOdd());
|
||||
|
||||
Integer b = bIn, a = aIn%bIn;
|
||||
int result = 1;
|
||||
|
||||
while (!!a)
|
||||
{
|
||||
unsigned i=0;
|
||||
while (a.GetBit(i)==0)
|
||||
i++;
|
||||
a>>=i;
|
||||
|
||||
if (i%2==1 && (b%8==3 || b%8==5))
|
||||
result = -result;
|
||||
|
||||
if (a%4==3 && b%4==3)
|
||||
result = -result;
|
||||
|
||||
std::swap(a, b);
|
||||
a %= b;
|
||||
}
|
||||
|
||||
return (b==1) ? result : 0;
|
||||
}
|
||||
|
||||
Integer Lucas(const Integer &e, const Integer &pIn, const Integer &n)
|
||||
{
|
||||
unsigned i = e.BitCount();
|
||||
if (i==0)
|
||||
return Integer::Two();
|
||||
|
||||
MontgomeryRepresentation m(n);
|
||||
Integer p=m.ConvertIn(pIn%n), two=m.ConvertIn(Integer::Two());
|
||||
Integer v=p, v1=m.Subtract(m.Square(p), two);
|
||||
|
||||
i--;
|
||||
while (i--)
|
||||
{
|
||||
if (e.GetBit(i))
|
||||
{
|
||||
// v = (v*v1 - p) % m;
|
||||
v = m.Subtract(m.Multiply(v,v1), p);
|
||||
// v1 = (v1*v1 - 2) % m;
|
||||
v1 = m.Subtract(m.Square(v1), two);
|
||||
}
|
||||
else
|
||||
{
|
||||
// v1 = (v*v1 - p) % m;
|
||||
v1 = m.Subtract(m.Multiply(v,v1), p);
|
||||
// v = (v*v - 2) % m;
|
||||
v = m.Subtract(m.Square(v), two);
|
||||
}
|
||||
}
|
||||
return m.ConvertOut(v);
|
||||
}
|
||||
|
||||
unsigned int FactoringWorkFactor(unsigned int n)
|
||||
{
|
||||
// extrapolated from the table in Odlyzko's "The Future of Integer Factorization"
|
||||
// updated to reflect the factoring of RSA-130
|
||||
if (n<5) return 0;
|
||||
else return (unsigned int)(2.4 * pow((double)n, double(1.0)/3.0) * pow(log(double(n)), double(2.0)/3.0) - 5);
|
||||
}
|
||||
|
||||
unsigned int DiscreteLogWorkFactor(unsigned int n)
|
||||
{
|
||||
// assuming discrete log takes about the same time as factoring
|
||||
if (n<5) return 0;
|
||||
else return (unsigned int)(2.4 * pow((double)n, double(1.0)/3.0) * pow(log(double(n)), double(2.0)/3.0) - 5);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
// 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 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 ****************
|
||||
|
||||
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);
|
||||
|
||||
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:
|
||||
virtual ~PrimeSelector() {}
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,112 +0,0 @@
|
||||
#ifndef CRYPTOPP_OIDS_H
|
||||
#define CRYPTOPP_OIDS_H
|
||||
|
||||
// crypto-related ASN.1 object identifiers
|
||||
|
||||
#include "asn.h"
|
||||
|
||||
namespace 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)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,105 +0,0 @@
|
||||
// osrng.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
// Thanks to Leonard Janke for the suggestion for AutoSeededRandomPool.
|
||||
|
||||
#include "global.h"
|
||||
#include "pch.h"
|
||||
#include "osrng.h"
|
||||
|
||||
#ifdef OS_RNG_AVAILABLE
|
||||
|
||||
#ifdef CRYPTOPP_WIN32_AVAILABLE
|
||||
#ifndef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x0400
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#include <wincrypt.h>
|
||||
#endif
|
||||
|
||||
#if defined(CRYPTOPP_UNIX_AVAILABLE)
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace 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)
|
||||
#elif defined(CRYPTOPP_UNIX_AVAILABLE)
|
||||
IntToString(errno)
|
||||
#else
|
||||
"(unknown)"
|
||||
#endif
|
||||
)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CRYPTOPP_WIN32_AVAILABLE
|
||||
|
||||
MicrosoftCryptoProvider::MicrosoftCryptoProvider()
|
||||
{
|
||||
if(!CryptAcquireContext(&m_hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
|
||||
{
|
||||
char buf[1024] = "";
|
||||
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
0, GetLastError(), 0, buf, sizeof(buf), NULL);
|
||||
throw OS_RNG_Err( std::string("CryptAcquireContext: ") + buf);
|
||||
}
|
||||
}
|
||||
|
||||
MicrosoftCryptoProvider::~MicrosoftCryptoProvider()
|
||||
{
|
||||
CryptReleaseContext(m_hProvider, 0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
NonblockingRng::NonblockingRng()
|
||||
{
|
||||
#if defined(CRYPTOPP_UNIX_AVAILABLE)
|
||||
m_fd = open("/dev/urandom",O_RDONLY);
|
||||
if (m_fd == -1)
|
||||
throw OS_RNG_Err("open /dev/urandom");
|
||||
#endif
|
||||
}
|
||||
|
||||
NonblockingRng::~NonblockingRng()
|
||||
{
|
||||
#if defined(CRYPTOPP_UNIX_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");
|
||||
#elif defined(CRYPTOPP_UNIX_AVAILABLE)
|
||||
if (read(m_fd, output, size) != int(size))
|
||||
throw OS_RNG_Err("read /dev/urandom");
|
||||
#else
|
||||
#warning No crypto source
|
||||
memset( output, 0, size );
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,60 +0,0 @@
|
||||
#ifndef CRYPTOPP_OSRNG_H
|
||||
#define CRYPTOPP_OSRNG_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
//removed
|
||||
//#include "randpool.h"
|
||||
|
||||
//added
|
||||
#include "cryptlib.h"
|
||||
#include "filters.h"
|
||||
|
||||
namespace CryptoPP {
|
||||
|
||||
//! Exception class for Operating-System Random Number Generator.
|
||||
class OS_RNG_Err : public Exception
|
||||
{
|
||||
public:
|
||||
OS_RNG_Err(const std::string &operation);
|
||||
};
|
||||
|
||||
#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
|
||||
#elif defined(CRYPTOPP_UNIX_AVAILABLE)
|
||||
int m_fd;
|
||||
#endif
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,13 +0,0 @@
|
||||
#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
|
||||
@@ -1,45 +0,0 @@
|
||||
// pkcspad.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "global.h"
|
||||
#include "pch.h"
|
||||
#include "pkcspad.h"
|
||||
#include <assert.h>
|
||||
|
||||
namespace 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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
#ifndef CRYPTOPP_PKCSPAD_H
|
||||
#define CRYPTOPP_PKCSPAD_H
|
||||
|
||||
#include "cryptlib.h"
|
||||
#include "pubkey.h"
|
||||
|
||||
namespace CryptoPP {
|
||||
|
||||
//! <a href="http://www.weidai.com/scan-mirror/ca.html#cem_PKCS1-1.5">EME-PKCS1-v1_5</a>
|
||||
|
||||
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
|
||||
{
|
||||
typedef PKCS1v15_SignatureMessageEncodingMethod SignatureMessageEncodingMethod;
|
||||
};
|
||||
|
||||
class SHA;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,103 +0,0 @@
|
||||
// pubkey.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "global.h"
|
||||
#include "pch.h"
|
||||
#include "pubkey.h"
|
||||
|
||||
namespace 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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,602 +0,0 @@
|
||||
// pubkey.h - written and placed in the public domain by Wei Dai
|
||||
|
||||
#ifndef CRYPTOPP_PUBKEY_H
|
||||
#define CRYPTOPP_PUBKEY_H
|
||||
|
||||
/** \file
|
||||
|
||||
This file contains helper classes/functions for implementing public key algorithms.
|
||||
|
||||
The class hierachies in this .h file tend to look like this:
|
||||
<pre>
|
||||
x1
|
||||
/ \
|
||||
y1 z1
|
||||
| |
|
||||
x2<y1> x2<z1>
|
||||
| |
|
||||
y2 z2
|
||||
| |
|
||||
x3<y2> x3<z2>
|
||||
| |
|
||||
y3 z3
|
||||
</pre>
|
||||
- x1, y1, z1 are abstract interface classes defined in cryptlib.h
|
||||
- x2, y2, z2 are implementations of the interfaces using "abstract policies", which
|
||||
are pure virtual functions that should return interfaces to interchangeable algorithms.
|
||||
These classes have "Base" suffixes.
|
||||
- x3, y3, z3 hold actual algorithms and implement those virtual functions.
|
||||
These classes have "Impl" suffixes.
|
||||
|
||||
The "TF_" prefix means an implementation using trapdoor functions on integers.
|
||||
The "DL_" prefix means an implementation using group operations (in groups where discrete log is hard).
|
||||
*/
|
||||
|
||||
#include "integer.h"
|
||||
#include "filters.h"
|
||||
#include "argnames.h"
|
||||
#include <memory>
|
||||
|
||||
#include "modarith.h"
|
||||
|
||||
// VC60 workaround: this macro is defined in shlobj.h and conflicts with a template parameter used in this file
|
||||
#undef INTERFACE
|
||||
|
||||
namespace CryptoPP {
|
||||
|
||||
Integer NR_EncodeDigest(unsigned int modulusBits, const byte *digest, unsigned int digestLen);
|
||||
Integer DSA_EncodeDigest(unsigned int modulusBits, const byte *digest, unsigned int digestLen);
|
||||
|
||||
// ********************************************************
|
||||
|
||||
//! .
|
||||
class TrapdoorFunctionBounds
|
||||
{
|
||||
public:
|
||||
virtual ~TrapdoorFunctionBounds() {}
|
||||
|
||||
virtual Integer PreimageBound() const =0;
|
||||
virtual Integer ImageBound() const =0;
|
||||
virtual Integer MaxPreimage() const {return --PreimageBound();}
|
||||
virtual Integer MaxImage() const {return --ImageBound();}
|
||||
};
|
||||
|
||||
//! .
|
||||
class RandomizedTrapdoorFunction : public TrapdoorFunctionBounds
|
||||
{
|
||||
public:
|
||||
virtual Integer ApplyRandomizedFunction(RandomNumberGenerator &rng, const Integer &x) const =0;
|
||||
virtual bool IsRandomized() const {return true;}
|
||||
};
|
||||
|
||||
//! .
|
||||
class TrapdoorFunction : public RandomizedTrapdoorFunction
|
||||
{
|
||||
public:
|
||||
Integer ApplyRandomizedFunction(RandomNumberGenerator &rng, const Integer &x) const
|
||||
{return ApplyFunction(x);}
|
||||
bool IsRandomized() const {return false;}
|
||||
|
||||
virtual Integer ApplyFunction(const Integer &x) const =0;
|
||||
};
|
||||
|
||||
//! .
|
||||
class RandomizedTrapdoorFunctionInverse
|
||||
{
|
||||
public:
|
||||
virtual ~RandomizedTrapdoorFunctionInverse() {}
|
||||
|
||||
virtual Integer CalculateRandomizedInverse(RandomNumberGenerator &rng, const Integer &x) const =0;
|
||||
virtual bool IsRandomized() const {return true;}
|
||||
};
|
||||
|
||||
//! .
|
||||
class TrapdoorFunctionInverse : public RandomizedTrapdoorFunctionInverse
|
||||
{
|
||||
public:
|
||||
virtual ~TrapdoorFunctionInverse() {}
|
||||
|
||||
Integer CalculateRandomizedInverse(RandomNumberGenerator &rng, const Integer &x) const
|
||||
{return CalculateInverse(rng, x);}
|
||||
bool IsRandomized() const {return false;}
|
||||
|
||||
virtual Integer CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const =0;
|
||||
};
|
||||
|
||||
// ********************************************************
|
||||
|
||||
//! .
|
||||
template <class TFI, class MEI>
|
||||
class TF_Base
|
||||
{
|
||||
public:
|
||||
virtual ~TF_Base() {}
|
||||
protected:
|
||||
virtual const TrapdoorFunctionBounds & GetTrapdoorFunctionBounds() const =0;
|
||||
|
||||
typedef TFI TrapdoorFunctionInterface;
|
||||
virtual const TrapdoorFunctionInterface & GetTrapdoorFunctionInterface() const =0;
|
||||
|
||||
typedef MEI MessageEncodingInterface;
|
||||
virtual const MessageEncodingInterface & GetMessageEncodingInterface() const =0;
|
||||
};
|
||||
|
||||
// ********************************************************
|
||||
|
||||
typedef std::pair<const byte *, unsigned int> HashIdentifier;
|
||||
|
||||
//! .
|
||||
class PK_SignatureMessageEncodingMethod
|
||||
{
|
||||
public:
|
||||
virtual ~PK_SignatureMessageEncodingMethod() {}
|
||||
|
||||
virtual unsigned int MaxRecoverableLength(unsigned int representativeBitLength, unsigned int hashIdentifierLength, unsigned int digestLength) const
|
||||
{return 0;}
|
||||
|
||||
bool IsProbabilistic() const
|
||||
{return true;}
|
||||
bool AllowNonrecoverablePart() const
|
||||
{throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");}
|
||||
virtual bool RecoverablePartFirst() const
|
||||
{throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");}
|
||||
|
||||
// for verification, DL
|
||||
virtual void ProcessSemisignature(HashTransformation &hash, const byte *semisignature, unsigned int semisignatureLength) const {}
|
||||
|
||||
// for signature
|
||||
virtual void ProcessRecoverableMessage(HashTransformation &hash,
|
||||
const byte *recoverableMessage, unsigned int recoverableMessageLength,
|
||||
const byte *presignature, unsigned int presignatureLength,
|
||||
SecByteBlock &semisignature) const
|
||||
{
|
||||
if (RecoverablePartFirst())
|
||||
assert(!"ProcessRecoverableMessage() not implemented");
|
||||
}
|
||||
|
||||
virtual void ComputeMessageRepresentative(RandomNumberGenerator &rng,
|
||||
const byte *recoverableMessage, unsigned int recoverableMessageLength,
|
||||
HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
|
||||
byte *representative, unsigned int representativeBitLength) const =0;
|
||||
|
||||
virtual bool VerifyMessageRepresentative(
|
||||
HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
|
||||
byte *representative, unsigned int representativeBitLength) const =0;
|
||||
|
||||
virtual DecodingResult RecoverMessageFromRepresentative( // for TF
|
||||
HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
|
||||
byte *representative, unsigned int representativeBitLength,
|
||||
byte *recoveredMessage) const
|
||||
{throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");}
|
||||
|
||||
virtual DecodingResult RecoverMessageFromSemisignature( // for DL
|
||||
HashTransformation &hash, HashIdentifier hashIdentifier,
|
||||
const byte *presignature, unsigned int presignatureLength,
|
||||
const byte *semisignature, unsigned int semisignatureLength,
|
||||
byte *recoveredMessage) const
|
||||
{throw NotImplemented("PK_MessageEncodingMethod: this signature scheme does not support message recovery");}
|
||||
|
||||
// VC60 workaround
|
||||
struct HashIdentifierLookup
|
||||
{
|
||||
template <class H> struct HashIdentifierLookup2
|
||||
{
|
||||
static HashIdentifier Lookup()
|
||||
{
|
||||
return HashIdentifier(NULL, 0);
|
||||
}
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
class PK_DeterministicSignatureMessageEncodingMethod : public PK_SignatureMessageEncodingMethod
|
||||
{
|
||||
public:
|
||||
bool VerifyMessageRepresentative(
|
||||
HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
|
||||
byte *representative, unsigned int representativeBitLength) const;
|
||||
};
|
||||
|
||||
class PK_RecoverableSignatureMessageEncodingMethod : public PK_SignatureMessageEncodingMethod
|
||||
{
|
||||
public:
|
||||
bool VerifyMessageRepresentative(
|
||||
HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
|
||||
byte *representative, unsigned int representativeBitLength) const;
|
||||
};
|
||||
|
||||
class DL_SignatureMessageEncodingMethod_DSA : public PK_DeterministicSignatureMessageEncodingMethod
|
||||
{
|
||||
public:
|
||||
void ComputeMessageRepresentative(RandomNumberGenerator &rng,
|
||||
const byte *recoverableMessage, unsigned int recoverableMessageLength,
|
||||
HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
|
||||
byte *representative, unsigned int representativeBitLength) const;
|
||||
};
|
||||
|
||||
class DL_SignatureMessageEncodingMethod_NR : public PK_DeterministicSignatureMessageEncodingMethod
|
||||
{
|
||||
public:
|
||||
void ComputeMessageRepresentative(RandomNumberGenerator &rng,
|
||||
const byte *recoverableMessage, unsigned int recoverableMessageLength,
|
||||
HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
|
||||
byte *representative, unsigned int representativeBitLength) const;
|
||||
};
|
||||
|
||||
class PK_MessageAccumulatorBase : public PK_MessageAccumulator
|
||||
{
|
||||
public:
|
||||
PK_MessageAccumulatorBase() : m_empty(true) {}
|
||||
|
||||
virtual HashTransformation & AccessHash() =0;
|
||||
|
||||
void Update(const byte *input, unsigned int length)
|
||||
{
|
||||
AccessHash().Update(input, length);
|
||||
m_empty = m_empty && length == 0;
|
||||
}
|
||||
|
||||
SecByteBlock m_recoverableMessage, m_representative, m_presignature, m_semisignature;
|
||||
Integer m_k, m_s;
|
||||
bool m_empty;
|
||||
};
|
||||
|
||||
template <class HASH_ALGORITHM>
|
||||
class PK_MessageAccumulatorImpl : public PK_MessageAccumulatorBase, protected ObjectHolder<HASH_ALGORITHM>
|
||||
{
|
||||
public:
|
||||
HashTransformation & AccessHash() {return this->m_object;}
|
||||
};
|
||||
|
||||
//! .
|
||||
template <class INTERFACE, class BASE>
|
||||
class TF_SignatureSchemeBase : public INTERFACE, protected BASE
|
||||
{
|
||||
public:
|
||||
unsigned int SignatureLength() const
|
||||
{return this->GetTrapdoorFunctionBounds().MaxPreimage().ByteCount();}
|
||||
unsigned int MaxRecoverableLength() const
|
||||
{return this->GetMessageEncodingInterface().MaxRecoverableLength(MessageRepresentativeBitLength(), GetHashIdentifier().second, GetDigestSize());}
|
||||
unsigned int MaxRecoverableLengthFromSignatureLength(unsigned int signatureLength) const
|
||||
{return this->MaxRecoverableLength();}
|
||||
|
||||
bool IsProbabilistic() const
|
||||
{return this->GetTrapdoorFunctionInterface().IsRandomized() || this->GetMessageEncodingInterface().IsProbabilistic();}
|
||||
bool AllowNonrecoverablePart() const
|
||||
{return this->GetMessageEncodingInterface().AllowNonrecoverablePart();}
|
||||
bool RecoverablePartFirst() const
|
||||
{return this->GetMessageEncodingInterface().RecoverablePartFirst();}
|
||||
|
||||
protected:
|
||||
unsigned int MessageRepresentativeLength() const {return BitsToBytes(MessageRepresentativeBitLength());}
|
||||
unsigned int MessageRepresentativeBitLength() const {return this->GetTrapdoorFunctionBounds().ImageBound().BitCount()-1;}
|
||||
virtual HashIdentifier GetHashIdentifier() const =0;
|
||||
virtual unsigned int GetDigestSize() const =0;
|
||||
};
|
||||
|
||||
//! .
|
||||
class TF_SignerBase : public TF_SignatureSchemeBase<PK_Signer, TF_Base<RandomizedTrapdoorFunctionInverse, PK_SignatureMessageEncodingMethod> >
|
||||
{
|
||||
public:
|
||||
void InputRecoverableMessage(PK_MessageAccumulator &messageAccumulator, const byte *recoverableMessage, unsigned int recoverableMessageLength) const;
|
||||
unsigned int SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart=true) const;
|
||||
};
|
||||
|
||||
//! .
|
||||
class TF_VerifierBase : public TF_SignatureSchemeBase<PK_Verifier, TF_Base<TrapdoorFunction, PK_SignatureMessageEncodingMethod> >
|
||||
{
|
||||
public:
|
||||
void InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, unsigned int signatureLength) const;
|
||||
bool VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const;
|
||||
DecodingResult RecoverAndRestart(byte *recoveredMessage, PK_MessageAccumulator &recoveryAccumulator) const;
|
||||
};
|
||||
|
||||
// ********************************************************
|
||||
|
||||
//! .
|
||||
template <class T1, class T2, class T3>
|
||||
struct TF_CryptoSchemeOptions
|
||||
{
|
||||
typedef T1 AlgorithmInfo;
|
||||
typedef T2 Keys;
|
||||
typedef typename Keys::PrivateKey PrivateKey;
|
||||
typedef typename Keys::PublicKey PublicKey;
|
||||
typedef T3 MessageEncodingMethod;
|
||||
};
|
||||
|
||||
//! .
|
||||
template <class T1, class T2, class T3, class T4>
|
||||
struct TF_SignatureSchemeOptions : public TF_CryptoSchemeOptions<T1, T2, T3>
|
||||
{
|
||||
typedef T4 HashFunction;
|
||||
};
|
||||
|
||||
//! .
|
||||
template <class KEYS>
|
||||
class PublicKeyCopier
|
||||
{
|
||||
public:
|
||||
virtual ~PublicKeyCopier() {}
|
||||
virtual void CopyKeyInto(typename KEYS::PublicKey &key) const =0;
|
||||
};
|
||||
|
||||
//! .
|
||||
template <class KEYS>
|
||||
class PrivateKeyCopier
|
||||
{
|
||||
public:
|
||||
virtual ~PrivateKeyCopier() {}
|
||||
virtual void CopyKeyInto(typename KEYS::PublicKey &key) const =0;
|
||||
virtual void CopyKeyInto(typename KEYS::PrivateKey &key) const =0;
|
||||
};
|
||||
|
||||
//! .
|
||||
template <class BASE, class SCHEME_OPTIONS, class KEY>
|
||||
class TF_ObjectImplBase : public AlgorithmImpl<BASE, typename SCHEME_OPTIONS::AlgorithmInfo>
|
||||
{
|
||||
public:
|
||||
typedef SCHEME_OPTIONS SchemeOptions;
|
||||
typedef KEY KeyClass;
|
||||
|
||||
PublicKey & AccessPublicKey() {return AccessKey();}
|
||||
const PublicKey & GetPublicKey() const {return GetKey();}
|
||||
|
||||
PrivateKey & AccessPrivateKey() {return AccessKey();}
|
||||
const PrivateKey & GetPrivateKey() const {return GetKey();}
|
||||
|
||||
virtual const KeyClass & GetKey() const =0;
|
||||
virtual KeyClass & AccessKey() =0;
|
||||
|
||||
const KeyClass & GetTrapdoorFunction() const {return GetKey();}
|
||||
|
||||
protected:
|
||||
const typename BASE::MessageEncodingInterface & GetMessageEncodingInterface() const
|
||||
{static typename SCHEME_OPTIONS::MessageEncodingMethod messageEncodingMethod; return messageEncodingMethod;}
|
||||
const TrapdoorFunctionBounds & GetTrapdoorFunctionBounds() const
|
||||
{return GetKey();}
|
||||
const typename BASE::TrapdoorFunctionInterface & GetTrapdoorFunctionInterface() const
|
||||
{return GetKey();}
|
||||
|
||||
// for signature scheme
|
||||
HashIdentifier GetHashIdentifier() const
|
||||
{
|
||||
typedef CPP_TYPENAME SchemeOptions::MessageEncodingMethod::HashIdentifierLookup::template HashIdentifierLookup2<CPP_TYPENAME SchemeOptions::HashFunction> L;
|
||||
return L::Lookup();
|
||||
/* typedef typename SchemeOptions::MessageEncodingMethod MEnMeth;
|
||||
typedef typename MEnMeth::HashIdentifierLookup HLookup;
|
||||
typedef typename SchemeOptions::HashFunction HashF;
|
||||
return HLookup::template HashIdentifierLookup2<HashF>::Lookup(); */
|
||||
}
|
||||
unsigned int GetDigestSize() const
|
||||
{
|
||||
typedef CPP_TYPENAME SchemeOptions::HashFunction H;
|
||||
return H::DIGESTSIZE;
|
||||
}
|
||||
};
|
||||
|
||||
//! .
|
||||
template <class BASE, class SCHEME_OPTIONS, class KEY>
|
||||
class TF_ObjectImplExtRef : public TF_ObjectImplBase<BASE, SCHEME_OPTIONS, KEY>
|
||||
{
|
||||
public:
|
||||
TF_ObjectImplExtRef(const KEY *pKey = NULL) : m_pKey(pKey) {}
|
||||
void SetKeyPtr(const KEY *pKey) {m_pKey = pKey;}
|
||||
|
||||
const KEY & GetKey() const {return *m_pKey;}
|
||||
KEY & AccessKey() {throw NotImplemented("TF_ObjectImplExtRef: cannot modify refererenced key");}
|
||||
|
||||
void CopyKeyInto(typename SCHEME_OPTIONS::PrivateKey &key) const {assert(false);}
|
||||
void CopyKeyInto(typename SCHEME_OPTIONS::PublicKey &key) const {assert(false);}
|
||||
|
||||
private:
|
||||
const KEY * m_pKey;
|
||||
};
|
||||
|
||||
//! .
|
||||
template <class BASE, class SCHEME_OPTIONS, class KEY>
|
||||
class TF_ObjectImpl : public TF_ObjectImplBase<BASE, SCHEME_OPTIONS, KEY>
|
||||
{
|
||||
public:
|
||||
const KEY & GetKey() const {return m_trapdoorFunction;}
|
||||
KEY & AccessKey() {return m_trapdoorFunction;}
|
||||
|
||||
private:
|
||||
KEY m_trapdoorFunction;
|
||||
};
|
||||
|
||||
//! .
|
||||
template <class BASE, class SCHEME_OPTIONS>
|
||||
class TF_PublicObjectImpl : public TF_ObjectImpl<BASE, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PublicKey>, public PublicKeyCopier<SCHEME_OPTIONS>
|
||||
{
|
||||
public:
|
||||
void CopyKeyInto(typename SCHEME_OPTIONS::PublicKey &key) const {key = this->GetKey();}
|
||||
};
|
||||
|
||||
//! .
|
||||
template <class BASE, class SCHEME_OPTIONS>
|
||||
class TF_PrivateObjectImpl : public TF_ObjectImpl<BASE, SCHEME_OPTIONS, typename SCHEME_OPTIONS::PrivateKey>, public PrivateKeyCopier<SCHEME_OPTIONS>
|
||||
{
|
||||
public:
|
||||
void CopyKeyInto(typename SCHEME_OPTIONS::PrivateKey &key) const {key = this->GetKey();}
|
||||
void CopyKeyInto(typename SCHEME_OPTIONS::PublicKey &key) const {key = this->GetKey();}
|
||||
};
|
||||
|
||||
//! .
|
||||
template <class SCHEME_OPTIONS>
|
||||
class TF_SignerImpl : public TF_PrivateObjectImpl<TF_SignerBase, SCHEME_OPTIONS>
|
||||
{
|
||||
PK_MessageAccumulator * NewSignatureAccumulator(RandomNumberGenerator &rng = NullRNG()) const
|
||||
{
|
||||
return new PK_MessageAccumulatorImpl<CPP_TYPENAME SCHEME_OPTIONS::HashFunction>;
|
||||
}
|
||||
};
|
||||
|
||||
//! .
|
||||
template <class SCHEME_OPTIONS>
|
||||
class TF_VerifierImpl : public TF_PublicObjectImpl<TF_VerifierBase, SCHEME_OPTIONS>
|
||||
{
|
||||
PK_MessageAccumulator * NewVerificationAccumulator() const
|
||||
{
|
||||
return new PK_MessageAccumulatorImpl<CPP_TYPENAME SCHEME_OPTIONS::HashFunction>;
|
||||
}
|
||||
};
|
||||
|
||||
// ********************************************************
|
||||
|
||||
void P1363_MGF1KDF2_Common(HashTransformation &hash, byte *output, unsigned int outputLength, const byte *input, unsigned int inputLength, bool mask, unsigned int counterStart);
|
||||
|
||||
// ********************************************************
|
||||
|
||||
//! .
|
||||
template <class H>
|
||||
class P1363_KDF2
|
||||
{
|
||||
public:
|
||||
static void DeriveKey(byte *output, unsigned int outputLength, const byte *input, unsigned int inputLength)
|
||||
{
|
||||
H h;
|
||||
P1363_MGF1KDF2_Common(h, output, outputLength, input, inputLength, false, 1);
|
||||
}
|
||||
};
|
||||
|
||||
// ********************************************************
|
||||
|
||||
template <class BASE>
|
||||
class PK_FinalTemplate : public BASE
|
||||
{
|
||||
public:
|
||||
PK_FinalTemplate() {}
|
||||
|
||||
PK_FinalTemplate(const Integer &v1)
|
||||
{this->AccessKey().Initialize(v1);}
|
||||
|
||||
PK_FinalTemplate(const typename BASE::KeyClass &key) {this->AccessKey().operator=(key);}
|
||||
|
||||
template <class T>
|
||||
PK_FinalTemplate(const PublicKeyCopier<T> &key)
|
||||
{key.CopyKeyInto(this->AccessKey());}
|
||||
|
||||
template <class T>
|
||||
PK_FinalTemplate(const PrivateKeyCopier<T> &key)
|
||||
{key.CopyKeyInto(this->AccessKey());}
|
||||
|
||||
PK_FinalTemplate(BufferedTransformation &bt) {this->AccessKey().BERDecode(bt);}
|
||||
|
||||
#if (defined(_MSC_VER) && _MSC_VER < 1300)
|
||||
|
||||
template <class T1, class T2>
|
||||
PK_FinalTemplate(T1 &v1, T2 &v2)
|
||||
{this->AccessKey().Initialize(v1, v2);}
|
||||
|
||||
template <class T1, class T2, class T3>
|
||||
PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3)
|
||||
{this->AccessKey().Initialize(v1, v2, v3);}
|
||||
|
||||
template <class T1, class T2, class T3, class T4>
|
||||
PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4)
|
||||
{this->AccessKey().Initialize(v1, v2, v3, v4);}
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5>
|
||||
PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4, T5 &v5)
|
||||
{this->AccessKey().Initialize(v1, v2, v3, v4, v5);}
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6>
|
||||
PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4, T5 &v5, T6 &v6)
|
||||
{this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6);}
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7>
|
||||
PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4, T5 &v5, T6 &v6, T7 &v7)
|
||||
{this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7);}
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
|
||||
PK_FinalTemplate(T1 &v1, T2 &v2, T3 &v3, T4 &v4, T5 &v5, T6 &v6, T7 &v7, T8 &v8)
|
||||
{this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7, v8);}
|
||||
|
||||
#else
|
||||
|
||||
template <class T1, class T2>
|
||||
PK_FinalTemplate(const T1 &v1, const T2 &v2)
|
||||
{this->AccessKey().Initialize(v1, v2);}
|
||||
|
||||
template <class T1, class T2, class T3>
|
||||
PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3)
|
||||
{this->AccessKey().Initialize(v1, v2, v3);}
|
||||
|
||||
template <class T1, class T2, class T3, class T4>
|
||||
PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4)
|
||||
{this->AccessKey().Initialize(v1, v2, v3, v4);}
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5>
|
||||
PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5)
|
||||
{this->AccessKey().Initialize(v1, v2, v3, v4, v5);}
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6>
|
||||
PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6)
|
||||
{this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6);}
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7>
|
||||
PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7)
|
||||
{this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7);}
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
|
||||
PK_FinalTemplate(const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7, const T8 &v8)
|
||||
{this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7, v8);}
|
||||
|
||||
template <class T1, class T2>
|
||||
PK_FinalTemplate(T1 &v1, const T2 &v2)
|
||||
{this->AccessKey().Initialize(v1, v2);}
|
||||
|
||||
template <class T1, class T2, class T3>
|
||||
PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3)
|
||||
{this->AccessKey().Initialize(v1, v2, v3);}
|
||||
|
||||
template <class T1, class T2, class T3, class T4>
|
||||
PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4)
|
||||
{this->AccessKey().Initialize(v1, v2, v3, v4);}
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5>
|
||||
PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5)
|
||||
{this->AccessKey().Initialize(v1, v2, v3, v4, v5);}
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6>
|
||||
PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6)
|
||||
{this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6);}
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7>
|
||||
PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7)
|
||||
{this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7);}
|
||||
|
||||
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
|
||||
PK_FinalTemplate(T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5, const T6 &v6, const T7 &v7, const T8 &v8)
|
||||
{this->AccessKey().Initialize(v1, v2, v3, v4, v5, v6, v7, v8);}
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
//! Base class for public key signature standard classes. These classes are used to select from variants of algorithms. Note that not all standards apply to all algorithms.
|
||||
struct SignatureStandard {};
|
||||
|
||||
template <class STANDARD, class H, class KEYS, class ALG_INFO> // VC60 workaround: doesn't work if KEYS is first parameter
|
||||
class TF_SS;
|
||||
|
||||
//! Trapdoor Function Based Signature Scheme
|
||||
template <class STANDARD, class H, class KEYS, class ALG_INFO = TF_SS<STANDARD, H, KEYS, int> > // VC60 workaround: doesn't work if KEYS is first parameter
|
||||
class TF_SS : public KEYS
|
||||
{
|
||||
public:
|
||||
//! see SignatureStandard for a list of standards
|
||||
typedef STANDARD Standard;
|
||||
typedef typename Standard::SignatureMessageEncodingMethod MessageEncodingMethod;
|
||||
typedef TF_SignatureSchemeOptions<ALG_INFO, KEYS, MessageEncodingMethod, H> SchemeOptions;
|
||||
|
||||
static std::string StaticAlgorithmName() {return KEYS::StaticAlgorithmName() + "/" + MessageEncodingMethod::StaticAlgorithmName() + "(" + H::StaticAlgorithmName() + ")";}
|
||||
|
||||
//! implements PK_Signer interface
|
||||
typedef PK_FinalTemplate<TF_SignerImpl<SchemeOptions> > Signer;
|
||||
//! implements PK_Verifier interface
|
||||
typedef PK_FinalTemplate<TF_VerifierImpl<SchemeOptions> > Verifier;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,519 +0,0 @@
|
||||
// queue.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "global.h"
|
||||
#include "pch.h"
|
||||
#include "queue.h"
|
||||
#include "filters.h"
|
||||
|
||||
namespace CryptoPP {
|
||||
|
||||
// this class for use by ByteQueue only
|
||||
class ByteQueueNode
|
||||
{
|
||||
public:
|
||||
ByteQueueNode(unsigned int maxSize)
|
||||
: buf(maxSize)
|
||||
{
|
||||
m_head = m_tail = 0;
|
||||
next = 0;
|
||||
}
|
||||
|
||||
inline unsigned int MaxSize() const {return buf.size();}
|
||||
|
||||
inline unsigned int CurrentSize() const
|
||||
{
|
||||
return m_tail-m_head;
|
||||
}
|
||||
|
||||
inline bool UsedUp() const
|
||||
{
|
||||
return (m_head==MaxSize());
|
||||
}
|
||||
|
||||
inline void Clear()
|
||||
{
|
||||
m_head = m_tail = 0;
|
||||
}
|
||||
|
||||
/* inline unsigned int Put(byte inByte)
|
||||
{
|
||||
if (MaxSize()==m_tail)
|
||||
return 0;
|
||||
|
||||
buf[m_tail++]=inByte;
|
||||
return 1;
|
||||
}
|
||||
*/
|
||||
inline unsigned int Put(const byte *begin, unsigned int length)
|
||||
{
|
||||
unsigned int l = STDMIN(length, MaxSize()-m_tail);
|
||||
memcpy(buf+m_tail, begin, l);
|
||||
m_tail += l;
|
||||
return l;
|
||||
}
|
||||
|
||||
inline unsigned int Peek(byte &outByte) const
|
||||
{
|
||||
if (m_tail==m_head)
|
||||
return 0;
|
||||
|
||||
outByte=buf[m_head];
|
||||
return 1;
|
||||
}
|
||||
|
||||
inline unsigned int Peek(byte *target, unsigned int copyMax) const
|
||||
{
|
||||
unsigned int len = STDMIN(copyMax, m_tail-m_head);
|
||||
memcpy(target, buf+m_head, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
inline unsigned int CopyTo(BufferedTransformation &target, const std::string &channel=BufferedTransformation::NULL_CHANNEL) const
|
||||
{
|
||||
unsigned int len = m_tail-m_head;
|
||||
target.ChannelPut(channel, buf+m_head, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
inline unsigned int CopyTo(BufferedTransformation &target, unsigned int copyMax, const std::string &channel=BufferedTransformation::NULL_CHANNEL) const
|
||||
{
|
||||
unsigned int len = STDMIN(copyMax, m_tail-m_head);
|
||||
target.ChannelPut(channel, buf+m_head, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
inline unsigned int Get(byte &outByte)
|
||||
{
|
||||
unsigned int len = Peek(outByte);
|
||||
m_head += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
inline unsigned int Get(byte *outString, unsigned int getMax)
|
||||
{
|
||||
unsigned int len = Peek(outString, getMax);
|
||||
m_head += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
inline unsigned int TransferTo(BufferedTransformation &target, const std::string &channel=BufferedTransformation::NULL_CHANNEL)
|
||||
{
|
||||
unsigned int len = m_tail-m_head;
|
||||
target.ChannelPutModifiable(channel, buf+m_head, len);
|
||||
m_head = m_tail;
|
||||
return len;
|
||||
}
|
||||
|
||||
inline unsigned int TransferTo(BufferedTransformation &target, unsigned int transferMax, const std::string &channel=BufferedTransformation::NULL_CHANNEL)
|
||||
{
|
||||
unsigned int len = STDMIN(transferMax, m_tail-m_head);
|
||||
target.ChannelPutModifiable(channel, buf+m_head, len);
|
||||
m_head += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
inline unsigned int Skip(unsigned int skipMax)
|
||||
{
|
||||
unsigned int len = STDMIN(skipMax, m_tail-m_head);
|
||||
m_head += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
inline byte operator[](unsigned int i) const
|
||||
{
|
||||
return buf[m_head+i];
|
||||
}
|
||||
|
||||
ByteQueueNode *next;
|
||||
|
||||
SecByteBlock buf;
|
||||
unsigned int m_head, m_tail;
|
||||
};
|
||||
|
||||
// ********************************************************
|
||||
|
||||
ByteQueue::ByteQueue(unsigned int m_nodeSize)
|
||||
: m_nodeSize(m_nodeSize), m_lazyLength(0)
|
||||
{
|
||||
m_head = m_tail = new ByteQueueNode(m_nodeSize);
|
||||
}
|
||||
|
||||
ByteQueue::ByteQueue(const ByteQueue ©)
|
||||
{
|
||||
CopyFrom(copy);
|
||||
}
|
||||
|
||||
void ByteQueue::CopyFrom(const ByteQueue ©)
|
||||
{
|
||||
m_lazyLength = 0;
|
||||
m_nodeSize = copy.m_nodeSize;
|
||||
m_head = m_tail = new ByteQueueNode(*copy.m_head);
|
||||
|
||||
for (ByteQueueNode *current=copy.m_head->next; current; current=current->next)
|
||||
{
|
||||
m_tail->next = new ByteQueueNode(*current);
|
||||
m_tail = m_tail->next;
|
||||
}
|
||||
|
||||
m_tail->next = NULL;
|
||||
|
||||
Put(copy.m_lazyString, copy.m_lazyLength);
|
||||
}
|
||||
|
||||
ByteQueue::~ByteQueue()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void ByteQueue::Destroy()
|
||||
{
|
||||
ByteQueueNode *next;
|
||||
|
||||
for (ByteQueueNode *current=m_head; current; current=next)
|
||||
{
|
||||
next=current->next;
|
||||
delete current;
|
||||
}
|
||||
}
|
||||
|
||||
void ByteQueue::IsolatedInitialize(const NameValuePairs ¶meters)
|
||||
{
|
||||
m_nodeSize = parameters.GetIntValueWithDefault("NodeSize", 256);
|
||||
Clear();
|
||||
}
|
||||
|
||||
unsigned long ByteQueue::CurrentSize() const
|
||||
{
|
||||
unsigned long size=0;
|
||||
|
||||
for (ByteQueueNode *current=m_head; current; current=current->next)
|
||||
size += current->CurrentSize();
|
||||
|
||||
return size + m_lazyLength;
|
||||
}
|
||||
|
||||
bool ByteQueue::IsEmpty() const
|
||||
{
|
||||
return m_head==m_tail && m_head->CurrentSize()==0 && m_lazyLength==0;
|
||||
}
|
||||
|
||||
void ByteQueue::Clear()
|
||||
{
|
||||
Destroy();
|
||||
m_head = m_tail = new ByteQueueNode(m_nodeSize);
|
||||
m_lazyLength = 0;
|
||||
}
|
||||
|
||||
unsigned int ByteQueue::Put2(const byte *inString, unsigned int length, int messageEnd, bool blocking)
|
||||
{
|
||||
if (m_lazyLength > 0)
|
||||
FinalizeLazyPut();
|
||||
|
||||
unsigned int len;
|
||||
while ((len=m_tail->Put(inString, length)) < length)
|
||||
{
|
||||
m_tail->next = new ByteQueueNode(m_nodeSize);
|
||||
m_tail = m_tail->next;
|
||||
inString += len;
|
||||
length -= len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ByteQueue::CleanupUsedNodes()
|
||||
{
|
||||
while (m_head != m_tail && m_head->UsedUp())
|
||||
{
|
||||
ByteQueueNode *temp=m_head;
|
||||
m_head=m_head->next;
|
||||
delete temp;
|
||||
}
|
||||
|
||||
if (m_head->CurrentSize() == 0)
|
||||
m_head->Clear();
|
||||
}
|
||||
|
||||
void ByteQueue::LazyPut(const byte *inString, unsigned int size)
|
||||
{
|
||||
if (m_lazyLength > 0)
|
||||
FinalizeLazyPut();
|
||||
m_lazyString = inString;
|
||||
m_lazyLength = size;
|
||||
}
|
||||
|
||||
void ByteQueue::UndoLazyPut(unsigned int size)
|
||||
{
|
||||
if (m_lazyLength < size)
|
||||
throw InvalidArgument("ByteQueue: size specified for UndoLazyPut is too large");
|
||||
|
||||
m_lazyLength -= size;
|
||||
}
|
||||
|
||||
void ByteQueue::FinalizeLazyPut()
|
||||
{
|
||||
unsigned int len = m_lazyLength;
|
||||
m_lazyLength = 0;
|
||||
if (len)
|
||||
Put(m_lazyString, len);
|
||||
}
|
||||
|
||||
unsigned int ByteQueue::Get(byte &outByte)
|
||||
{
|
||||
if (m_head->Get(outByte))
|
||||
{
|
||||
if (m_head->UsedUp())
|
||||
CleanupUsedNodes();
|
||||
return 1;
|
||||
}
|
||||
else if (m_lazyLength > 0)
|
||||
{
|
||||
outByte = *m_lazyString++;
|
||||
m_lazyLength--;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int ByteQueue::Get(byte *outString, unsigned int getMax)
|
||||
{
|
||||
ArraySink sink(outString, getMax);
|
||||
return TransferTo(sink, getMax);
|
||||
}
|
||||
|
||||
unsigned int ByteQueue::Peek(byte &outByte) const
|
||||
{
|
||||
if (m_head->Peek(outByte))
|
||||
return 1;
|
||||
else if (m_lazyLength > 0)
|
||||
{
|
||||
outByte = *m_lazyString;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int ByteQueue::Peek(byte *outString, unsigned int peekMax) const
|
||||
{
|
||||
ArraySink sink(outString, peekMax);
|
||||
return CopyTo(sink, peekMax);
|
||||
}
|
||||
|
||||
unsigned int ByteQueue::TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel, bool blocking)
|
||||
{
|
||||
if (blocking)
|
||||
{
|
||||
unsigned long bytesLeft = transferBytes;
|
||||
for (ByteQueueNode *current=m_head; bytesLeft && current; current=current->next)
|
||||
bytesLeft -= current->TransferTo(target, bytesLeft, channel);
|
||||
CleanupUsedNodes();
|
||||
|
||||
unsigned int len = (unsigned int)STDMIN(bytesLeft, (unsigned long)m_lazyLength);
|
||||
if (len)
|
||||
{
|
||||
target.ChannelPut(channel, m_lazyString, len);
|
||||
m_lazyString += len;
|
||||
m_lazyLength -= len;
|
||||
bytesLeft -= len;
|
||||
}
|
||||
transferBytes -= bytesLeft;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Walker walker(*this);
|
||||
unsigned int blockedBytes = walker.TransferTo2(target, transferBytes, channel, blocking);
|
||||
Skip(transferBytes);
|
||||
return blockedBytes;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int ByteQueue::CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end, const std::string &channel, bool blocking) const
|
||||
{
|
||||
Walker walker(*this);
|
||||
walker.Skip(begin);
|
||||
unsigned long transferBytes = end-begin;
|
||||
unsigned int blockedBytes = walker.TransferTo2(target, transferBytes, channel, blocking);
|
||||
begin += transferBytes;
|
||||
return blockedBytes;
|
||||
}
|
||||
|
||||
void ByteQueue::Unget(byte inByte)
|
||||
{
|
||||
Unget(&inByte, 1);
|
||||
}
|
||||
|
||||
void ByteQueue::Unget(const byte *inString, unsigned int length)
|
||||
{
|
||||
// TODO: make this more efficient
|
||||
ByteQueueNode *newHead = new ByteQueueNode(length);
|
||||
newHead->next = m_head;
|
||||
m_head = newHead;
|
||||
m_head->Put(inString, length);
|
||||
}
|
||||
|
||||
const byte * ByteQueue::Spy(unsigned int &contiguousSize) const
|
||||
{
|
||||
contiguousSize = m_head->m_tail - m_head->m_head;
|
||||
if (contiguousSize == 0 && m_lazyLength > 0)
|
||||
{
|
||||
contiguousSize = m_lazyLength;
|
||||
return m_lazyString;
|
||||
}
|
||||
else
|
||||
return m_head->buf + m_head->m_head;
|
||||
}
|
||||
|
||||
byte * ByteQueue::CreatePutSpace(unsigned int &size)
|
||||
{
|
||||
if (m_lazyLength > 0)
|
||||
FinalizeLazyPut();
|
||||
|
||||
if (m_tail->m_tail == m_tail->MaxSize())
|
||||
{
|
||||
m_tail->next = new ByteQueueNode(size < m_nodeSize ? m_nodeSize : STDMAX(m_nodeSize, 1024U));
|
||||
m_tail = m_tail->next;
|
||||
}
|
||||
|
||||
size = m_tail->MaxSize() - m_tail->m_tail;
|
||||
return m_tail->buf + m_tail->m_tail;
|
||||
}
|
||||
|
||||
ByteQueue & ByteQueue::operator=(const ByteQueue &rhs)
|
||||
{
|
||||
Destroy();
|
||||
CopyFrom(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool ByteQueue::operator==(const ByteQueue &rhs) const
|
||||
{
|
||||
const unsigned long currentSize = CurrentSize();
|
||||
|
||||
if (currentSize != rhs.CurrentSize())
|
||||
return false;
|
||||
|
||||
Walker walker1(*this), walker2(rhs);
|
||||
byte b1, b2;
|
||||
|
||||
while (walker1.Get(b1) && walker2.Get(b2))
|
||||
if (b1 != b2)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
byte ByteQueue::operator[](unsigned long i) const
|
||||
{
|
||||
for (ByteQueueNode *current=m_head; current; current=current->next)
|
||||
{
|
||||
if (i < current->CurrentSize())
|
||||
return (*current)[i];
|
||||
|
||||
i -= current->CurrentSize();
|
||||
}
|
||||
|
||||
assert(i < m_lazyLength);
|
||||
return m_lazyString[i];
|
||||
}
|
||||
|
||||
void ByteQueue::swap(ByteQueue &rhs)
|
||||
{
|
||||
std::swap(m_nodeSize, rhs.m_nodeSize);
|
||||
std::swap(m_head, rhs.m_head);
|
||||
std::swap(m_tail, rhs.m_tail);
|
||||
std::swap(m_lazyString, rhs.m_lazyString);
|
||||
std::swap(m_lazyLength, rhs.m_lazyLength);
|
||||
}
|
||||
|
||||
// ********************************************************
|
||||
|
||||
void ByteQueue::Walker::IsolatedInitialize(const NameValuePairs ¶meters)
|
||||
{
|
||||
m_node = m_queue.m_head;
|
||||
m_position = 0;
|
||||
m_offset = 0;
|
||||
m_lazyString = m_queue.m_lazyString;
|
||||
m_lazyLength = m_queue.m_lazyLength;
|
||||
}
|
||||
|
||||
unsigned int ByteQueue::Walker::Get(byte &outByte)
|
||||
{
|
||||
ArraySink sink(&outByte, 1);
|
||||
return TransferTo(sink, 1);
|
||||
}
|
||||
|
||||
unsigned int ByteQueue::Walker::Get(byte *outString, unsigned int getMax)
|
||||
{
|
||||
ArraySink sink(outString, getMax);
|
||||
return TransferTo(sink, getMax);
|
||||
}
|
||||
|
||||
unsigned int ByteQueue::Walker::Peek(byte &outByte) const
|
||||
{
|
||||
ArraySink sink(&outByte, 1);
|
||||
return CopyTo(sink, 1);
|
||||
}
|
||||
|
||||
unsigned int ByteQueue::Walker::Peek(byte *outString, unsigned int peekMax) const
|
||||
{
|
||||
ArraySink sink(outString, peekMax);
|
||||
return CopyTo(sink, peekMax);
|
||||
}
|
||||
|
||||
unsigned int ByteQueue::Walker::TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel, bool blocking)
|
||||
{
|
||||
unsigned long bytesLeft = transferBytes;
|
||||
unsigned int blockedBytes = 0;
|
||||
|
||||
while (m_node)
|
||||
{
|
||||
unsigned int len = STDMIN(bytesLeft, (unsigned long)m_node->CurrentSize()-m_offset);
|
||||
blockedBytes = target.ChannelPut2(channel, m_node->buf+m_node->m_head+m_offset, len, 0, blocking);
|
||||
|
||||
if (blockedBytes)
|
||||
goto done;
|
||||
|
||||
m_position += len;
|
||||
bytesLeft -= len;
|
||||
|
||||
if (!bytesLeft)
|
||||
{
|
||||
m_offset += len;
|
||||
goto done;
|
||||
}
|
||||
|
||||
m_node = m_node->next;
|
||||
m_offset = 0;
|
||||
}
|
||||
|
||||
if (bytesLeft && m_lazyLength)
|
||||
{
|
||||
unsigned int len = (unsigned int)STDMIN(bytesLeft, (unsigned long)m_lazyLength);
|
||||
unsigned int blockedBytes = target.ChannelPut2(channel, m_lazyString, len, 0, blocking);
|
||||
if (blockedBytes)
|
||||
goto done;
|
||||
|
||||
m_lazyString += len;
|
||||
m_lazyLength -= len;
|
||||
bytesLeft -= len;
|
||||
}
|
||||
|
||||
done:
|
||||
transferBytes -= bytesLeft;
|
||||
return blockedBytes;
|
||||
}
|
||||
|
||||
unsigned int ByteQueue::Walker::CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end, const std::string &channel, bool blocking) const
|
||||
{
|
||||
Walker walker(*this);
|
||||
walker.Skip(begin);
|
||||
unsigned long transferBytes = end-begin;
|
||||
unsigned int blockedBytes = walker.TransferTo2(target, transferBytes, channel, blocking);
|
||||
begin += transferBytes;
|
||||
return blockedBytes;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,128 +0,0 @@
|
||||
// specification file for an unlimited queue for storing bytes
|
||||
|
||||
#ifndef CRYPTOPP_QUEUE_H
|
||||
#define CRYPTOPP_QUEUE_H
|
||||
|
||||
#include "simple.h"
|
||||
//#include <algorithm>
|
||||
|
||||
namespace CryptoPP {
|
||||
|
||||
/** The queue is implemented as a linked list of byte arrays, but you don't need to
|
||||
know about that. So just ignore this next line. :) */
|
||||
class ByteQueueNode;
|
||||
|
||||
//! Byte Queue
|
||||
class ByteQueue : public Bufferless<BufferedTransformation>
|
||||
{
|
||||
public:
|
||||
ByteQueue(unsigned int m_nodeSize=256);
|
||||
ByteQueue(const ByteQueue ©);
|
||||
~ByteQueue();
|
||||
|
||||
unsigned long MaxRetrievable() const
|
||||
{return CurrentSize();}
|
||||
bool AnyRetrievable() const
|
||||
{return !IsEmpty();}
|
||||
|
||||
void IsolatedInitialize(const NameValuePairs ¶meters);
|
||||
byte * CreatePutSpace(unsigned int &size);
|
||||
unsigned int Put2(const byte *inString, unsigned int length, int messageEnd, bool blocking);
|
||||
|
||||
unsigned int Get(byte &outByte);
|
||||
unsigned int Get(byte *outString, unsigned int getMax);
|
||||
|
||||
unsigned int Peek(byte &outByte) const;
|
||||
unsigned int Peek(byte *outString, unsigned int peekMax) const;
|
||||
|
||||
unsigned int TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel=NULL_CHANNEL, bool blocking=true);
|
||||
unsigned int CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end=ULONG_MAX, const std::string &channel=NULL_CHANNEL, bool blocking=true) const;
|
||||
|
||||
// these member functions are not inherited
|
||||
void SetNodeSize(unsigned int nodeSize) {m_nodeSize = nodeSize;}
|
||||
|
||||
unsigned long CurrentSize() const;
|
||||
bool IsEmpty() const;
|
||||
|
||||
void Clear();
|
||||
|
||||
void Unget(byte inByte);
|
||||
void Unget(const byte *inString, unsigned int length);
|
||||
|
||||
const byte * Spy(unsigned int &contiguousSize) const;
|
||||
|
||||
void LazyPut(const byte *inString, unsigned int size);
|
||||
void UndoLazyPut(unsigned int size);
|
||||
void FinalizeLazyPut();
|
||||
|
||||
ByteQueue & operator=(const ByteQueue &rhs);
|
||||
bool operator==(const ByteQueue &rhs) const;
|
||||
byte operator[](unsigned long i) const;
|
||||
void swap(ByteQueue &rhs);
|
||||
|
||||
class Walker : public InputRejecting<BufferedTransformation>
|
||||
{
|
||||
public:
|
||||
Walker(const ByteQueue &queue)
|
||||
: m_queue(queue) {Initialize();}
|
||||
|
||||
unsigned long GetCurrentPosition() {return m_position;}
|
||||
|
||||
unsigned long MaxRetrievable() const
|
||||
{return m_queue.CurrentSize() - m_position;}
|
||||
|
||||
void IsolatedInitialize(const NameValuePairs ¶meters);
|
||||
|
||||
unsigned int Get(byte &outByte);
|
||||
unsigned int Get(byte *outString, unsigned int getMax);
|
||||
|
||||
unsigned int Peek(byte &outByte) const;
|
||||
unsigned int Peek(byte *outString, unsigned int peekMax) const;
|
||||
|
||||
unsigned int TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel=NULL_CHANNEL, bool blocking=true);
|
||||
unsigned int CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end=ULONG_MAX, const std::string &channel=NULL_CHANNEL, bool blocking=true) const;
|
||||
|
||||
private:
|
||||
const ByteQueue &m_queue;
|
||||
const ByteQueueNode *m_node;
|
||||
unsigned long m_position;
|
||||
unsigned int m_offset;
|
||||
const byte *m_lazyString;
|
||||
unsigned int m_lazyLength;
|
||||
};
|
||||
|
||||
friend class Walker;
|
||||
|
||||
private:
|
||||
void CleanupUsedNodes();
|
||||
void CopyFrom(const ByteQueue ©);
|
||||
void Destroy();
|
||||
|
||||
unsigned int m_nodeSize;
|
||||
ByteQueueNode *m_head, *m_tail;
|
||||
const byte *m_lazyString;
|
||||
unsigned int m_lazyLength;
|
||||
};
|
||||
|
||||
//! use this to make sure LazyPut is finalized in event of exception
|
||||
class LazyPutter
|
||||
{
|
||||
public:
|
||||
LazyPutter(ByteQueue &bq, const byte *inString, unsigned int size)
|
||||
: m_bq(bq) {bq.LazyPut(inString, size);}
|
||||
~LazyPutter()
|
||||
{try {m_bq.FinalizeLazyPut();} catch(...) {}}
|
||||
private:
|
||||
ByteQueue &m_bq;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
NAMESPACE_BEGIN(std)
|
||||
template<> inline void swap(CryptoPP::ByteQueue &a, CryptoPP::ByteQueue &b)
|
||||
{
|
||||
a.swap(b);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,236 +0,0 @@
|
||||
// rsa.cpp - written and placed in the public domain by Wei Dai
|
||||
|
||||
#include "global.h"
|
||||
#include "pch.h"
|
||||
#include "rsa.h"
|
||||
#include "asn.h"
|
||||
#include "oids.h"
|
||||
#include "modarith.h"
|
||||
#include "nbtheory.h"
|
||||
#include "sha.h"
|
||||
#include "algparam.h"
|
||||
|
||||
|
||||
namespace CryptoPP {
|
||||
|
||||
|
||||
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) {}
|
||||
virtual ~RSAPrimeSelector() { }
|
||||
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);
|
||||
|
||||
ASSERT( modulusSize >= 16 );
|
||||
|
||||
m_e = alg.GetValueWithDefault("PublicExponent", Integer(17));
|
||||
|
||||
ASSERT( m_e >= 3 );
|
||||
ASSERT( !m_e.IsEven() );
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
ASSERT( modn.Exponentiate(y, m_e) == x ); // check
|
||||
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)
|
||||
;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,123 +0,0 @@
|
||||
#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 "integer.h"
|
||||
#include "asn.h"
|
||||
|
||||
namespace 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/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 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;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,388 +0,0 @@
|
||||
// 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 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:
|
||||
//added
|
||||
typedef T value_type;
|
||||
|
||||
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_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
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,110 +0,0 @@
|
||||
// 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 CryptoPP {
|
||||
|
||||
//! .
|
||||
template <unsigned int N>
|
||||
class FixedBlockSize
|
||||
{
|
||||
public:
|
||||
enum {BLOCKSIZE = N};
|
||||
};
|
||||
|
||||
// ************** 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;}
|
||||
};
|
||||
|
||||
// ************** implementation helper for SimpledKeyed ***************
|
||||
|
||||
template <class T>
|
||||
static inline void CheckedSetKey(T *obj, Empty empty, const byte *key, unsigned int length, const NameValuePairs ¶m)
|
||||
{
|
||||
obj->ThrowIfInvalidKeyLength(length);
|
||||
obj->UncheckedSetKey(key, length);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static inline void CheckedSetKey(T *obj, CipherDir dir, const byte *key, unsigned int length, const NameValuePairs ¶m)
|
||||
{
|
||||
obj->ThrowIfInvalidKeyLength(length);
|
||||
obj->UncheckedSetKey(dir, key, length);
|
||||
}
|
||||
|
||||
//! .
|
||||
template <class BASE, class INFO = BASE>
|
||||
class SimpleKeyingInterfaceImpl : public BASE
|
||||
{
|
||||
public:
|
||||
unsigned int MinKeyLength() const {return INFO::MIN_KEYLENGTH;}
|
||||
unsigned int MaxKeyLength() const {return (unsigned int)INFO::MAX_KEYLENGTH;}
|
||||
unsigned int DefaultKeyLength() const {return INFO::DEFAULT_KEYLENGTH;}
|
||||
unsigned int GetValidKeyLength(unsigned int n) const {return INFO::StaticGetValidKeyLength(n);}
|
||||
typename BASE::IV_Requirement IVRequirement() const {return (typename BASE::IV_Requirement)INFO::IV_REQUIREMENT;}
|
||||
|
||||
protected:
|
||||
void AssertValidKeyLength(unsigned int length) {assert(GetValidKeyLength(length) == length);}
|
||||
};
|
||||
|
||||
template <class INFO, class INTERFACE = BlockCipher>
|
||||
class BlockCipherBaseTemplate : public AlgorithmImpl<SimpleKeyingInterfaceImpl<TwoBases<INFO, INTERFACE> > >
|
||||
{
|
||||
public:
|
||||
unsigned int BlockSize() const {return this->BLOCKSIZE;}
|
||||
};
|
||||
|
||||
//! .
|
||||
template <CipherDir DIR, class BASE>
|
||||
class BlockCipherTemplate : public BASE
|
||||
{
|
||||
public:
|
||||
BlockCipherTemplate() {}
|
||||
BlockCipherTemplate(const byte *key)
|
||||
{SetKey(key, this->DEFAULT_KEYLENGTH);}
|
||||
BlockCipherTemplate(const byte *key, unsigned int length)
|
||||
{SetKey(key, length);}
|
||||
BlockCipherTemplate(const byte *key, unsigned int length, unsigned int rounds)
|
||||
{this->SetKeyWithRounds(key, length, rounds);}
|
||||
|
||||
bool IsForwardTransformation() const {return DIR == ENCRYPTION;}
|
||||
|
||||
void SetKey(const byte *key, unsigned int length, const NameValuePairs ¶m = g_nullNameValuePairs)
|
||||
{
|
||||
CheckedSetKey(this, DIR, key, length, param);
|
||||
}
|
||||
|
||||
Clonable * Clone() const {return new BlockCipherTemplate<DIR, BASE>(*this);}
|
||||
};
|
||||
|
||||
// ************** documentation ***************
|
||||
|
||||
/*! \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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,84 +0,0 @@
|
||||
// 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 "global.h"
|
||||
#include "pch.h"
|
||||
#include "sha.h"
|
||||
#include "misc.h"
|
||||
|
||||
namespace 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
|
||||
|
||||
// *************************************************************
|
||||
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
#ifndef CRYPTOPP_SHA_H
|
||||
#define CRYPTOPP_SHA_H
|
||||
|
||||
#include "iterhash.h"
|
||||
|
||||
namespace 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;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,190 +0,0 @@
|
||||
// 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 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") {}
|
||||
};
|
||||
|
||||
//! .
|
||||
// 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:
|
||||
using T::NULL_CHANNEL;
|
||||
|
||||
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 = this->AttachedTransformation();
|
||||
return attached && propagation ? attached->ChannelFlush(channel, hardFlush, propagation-1, blocking) : false;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool InputBufferIsEmpty() const {return false;}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class InputRejecting : public T
|
||||
{
|
||||
public:
|
||||
InputRejecting() {}
|
||||
InputRejecting(BufferedTransformation *q) : T(q) {}
|
||||
|
||||
protected:
|
||||
struct InputRejected : public NotImplemented
|
||||
{InputRejected() : NotImplemented("BufferedTransformation: this object doesn't allow input") {}};
|
||||
|
||||
// shouldn't be calling these functions on this class
|
||||
unsigned int Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking)
|
||||
{throw InputRejected();}
|
||||
bool IsolatedFlush(bool, bool) {return false;}
|
||||
bool IsolatedMessageSeriesEnd(bool) {throw InputRejected();}
|
||||
|
||||
unsigned int ChannelPut2(const std::string &channel, const byte *begin, unsigned int length, int messageEnd, bool blocking)
|
||||
{throw InputRejected();}
|
||||
bool ChannelMessageSeriesEnd(const std::string &, int, bool) {throw InputRejected();}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class CustomSignalPropagation : public T
|
||||
{
|
||||
public:
|
||||
CustomSignalPropagation() {}
|
||||
CustomSignalPropagation(BufferedTransformation *q) : T(q) {}
|
||||
|
||||
virtual void Initialize(const NameValuePairs ¶meters=g_nullNameValuePairs, int propagation=-1) =0;
|
||||
virtual bool Flush(bool hardFlush, int propagation=-1, bool blocking=true) =0;
|
||||
|
||||
private:
|
||||
void IsolatedInitialize(const NameValuePairs ¶meters) {assert(false);}
|
||||
bool IsolatedFlush(bool hardFlush, bool blocking) {assert(false); return false;}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class AutoSignaling : public T
|
||||
{
|
||||
public:
|
||||
AutoSignaling(int propagation=-1) : m_autoSignalPropagation(propagation) {}
|
||||
AutoSignaling(BufferedTransformation *q, int propagation=-1) : T(q), m_autoSignalPropagation(propagation) {}
|
||||
|
||||
void SetAutoSignalPropagation(int propagation)
|
||||
{m_autoSignalPropagation = propagation;}
|
||||
int GetAutoSignalPropagation() const
|
||||
{return m_autoSignalPropagation;}
|
||||
|
||||
private:
|
||||
int m_autoSignalPropagation;
|
||||
};
|
||||
|
||||
//! A BufferedTransformation that only contains pre-existing data as "output"
|
||||
class Store : public AutoSignaling<InputRejecting<BufferedTransformation> >
|
||||
{
|
||||
public:
|
||||
Store() : m_messageEnd(false) {}
|
||||
|
||||
void IsolatedInitialize(const NameValuePairs ¶meters)
|
||||
{
|
||||
m_messageEnd = false;
|
||||
StoreInitialize(parameters);
|
||||
}
|
||||
|
||||
unsigned int NumberOfMessages() const {return m_messageEnd ? 0 : 1;}
|
||||
bool GetNextMessage();
|
||||
unsigned int CopyMessagesTo(BufferedTransformation &target, unsigned int count=UINT_MAX, const std::string &channel=NULL_CHANNEL) const;
|
||||
|
||||
protected:
|
||||
virtual void StoreInitialize(const NameValuePairs ¶meters) =0;
|
||||
|
||||
bool m_messageEnd;
|
||||
};
|
||||
|
||||
//! A BufferedTransformation that doesn't produce any retrievable output
|
||||
class Sink : public BufferedTransformation
|
||||
{
|
||||
protected:
|
||||
// make these functions protected to help prevent unintentional calls to them
|
||||
BufferedTransformation::Get;
|
||||
BufferedTransformation::Peek;
|
||||
BufferedTransformation::TransferTo;
|
||||
BufferedTransformation::CopyTo;
|
||||
BufferedTransformation::CopyRangeTo;
|
||||
BufferedTransformation::TransferMessagesTo;
|
||||
BufferedTransformation::CopyMessagesTo;
|
||||
BufferedTransformation::TransferAllTo;
|
||||
BufferedTransformation::CopyAllTo;
|
||||
unsigned int TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel=NULL_CHANNEL, bool blocking=true)
|
||||
{transferBytes = 0; return 0;}
|
||||
unsigned int CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end=ULONG_MAX, const std::string &channel=NULL_CHANNEL, bool blocking=true) const
|
||||
{return 0;}
|
||||
};
|
||||
|
||||
class BitBucket : public Bufferless<Sink>
|
||||
{
|
||||
public:
|
||||
std::string AlgorithmName() const {return "BitBucket";}
|
||||
void IsolatedInitialize(const NameValuePairs ¶meters) {}
|
||||
unsigned int Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking)
|
||||
{return 0;}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,45 +0,0 @@
|
||||
#ifndef CRYPTOPP_SMARTPTR_H
|
||||
#define CRYPTOPP_SMARTPTR_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
namespace 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;}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,103 +0,0 @@
|
||||
#ifndef CRYPTOPP_WORDS_H
|
||||
#define CRYPTOPP_WORDS_H
|
||||
|
||||
#include "misc.h"
|
||||
|
||||
namespace 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user