changeset 209:f7fb9a523442 draft

added a subset of Crypto++ 5.6.0 with 48% faster ASM SHA-256, combined speedup 2.5x faster vs 0.3.3, thanks BlackEye for figuring out the alignment problem git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@114 1a98c847-1fd6-4fd8-948a-caf3550aa51b
author s_nakamoto <s_nakamoto@1a98c847-1fd6-4fd8-948a-caf3550aa51b>
date Tue, 27 Jul 2010 18:14:32 +0000
parents f4240746185d
children 3f0039575479
files cryptopp/License.txt cryptopp/Readme.txt cryptopp/config.h cryptopp/cpu.cpp cryptopp/cpu.h cryptopp/cryptlib.h cryptopp/iterhash.h cryptopp/misc.h cryptopp/pch.h cryptopp/secblock.h cryptopp/sha.cpp cryptopp/sha.h cryptopp/simple.h cryptopp/smartptr.h cryptopp/stdcpp.h main.cpp makefile.mingw makefile.osx makefile.unix makefile.vc sha.cpp sha.h util.h
diffstat 23 files changed, 6087 insertions(+), 895 deletions(-) [+]
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/cryptopp/License.txt
@@ -0,0 +1,67 @@
+Compilation Copyright (c) 1995-2009 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
+Andrew M. Kuchling - md2.cpp, md4.cpp
+Colin Plumb - md5.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
+Kevin Springle - camellia.cpp, shacal2.cpp, ttmac.cpp, whrlpool.cpp, ripemd.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.
new file mode 100644
--- /dev/null
+++ b/cryptopp/Readme.txt
@@ -0,0 +1,429 @@
+Crypto++: a C++ Class Library of Cryptographic Schemes
+Version 5.6.0 (3/15/2009)
+
+Crypto++ Library is a free C++ class library of cryptographic schemes.
+Currently the library contains the following algorithms:
+
+                   algorithm type  name
+
+ authenticated encryption schemes  GCM, CCM, EAX
+ 
+        high speed stream ciphers  Panama, Sosemanuk, Salsa20, XSalsa20
+
+           AES and AES candidates  AES (Rijndael), RC6, MARS, Twofish, Serpent,
+                                   CAST-256
+
+                                   IDEA, Triple-DES (DES-EDE2 and DES-EDE3),
+              other block ciphers  Camellia, SEED, RC5, Blowfish, TEA, XTEA,
+                                   Skipjack, SHACAL-2
+
+  block cipher modes of operation  ECB, CBC, CBC ciphertext stealing (CTS),
+                                   CFB, OFB, counter mode (CTR)
+
+     message authentication codes  VMAC, HMAC, CMAC, CBC-MAC, DMAC, 
+                                   Two-Track-MAC
+
+                                   SHA-1, SHA-2 (SHA-224, SHA-256, SHA-384, and
+                   hash functions  SHA-512), Tiger, WHIRLPOOL, RIPEMD-128,
+                                   RIPEMD-256, RIPEMD-160, RIPEMD-320
+
+                                   RSA, DSA, ElGamal, Nyberg-Rueppel (NR),
+          public-key cryptography  Rabin, Rabin-Williams (RW), LUC, LUCELG,
+                                   DLIES (variants of DHAES), ESIGN
+
+   padding schemes for public-key  PKCS#1 v2.0, OAEP, PSS, PSSR, IEEE P1363
+                          systems  EMSA2 and EMSA5
+
+                                   Diffie-Hellman (DH), Unified Diffie-Hellman
+            key agreement schemes  (DH2), Menezes-Qu-Vanstone (MQV), LUCDIF,
+                                   XTR-DH
+
+      elliptic curve cryptography  ECDSA, ECNR, ECIES, ECDH, ECMQV
+
+          insecure or obsolescent  MD2, MD4, MD5, Panama Hash, DES, ARC4, SEAL
+algorithms retained for backwards  3.0, WAKE, WAKE-OFB, DESX (DES-XEX3), RC2,
+     compatibility and historical  SAFER, 3-WAY, GOST, SHARK, CAST-128, Square
+                            value
+
+Other features include:
+
+  * pseudo random number generators (PRNG): ANSI X9.17 appendix C, RandomPool
+  * password based key derivation functions: PBKDF1 and PBKDF2 from PKCS #5,
+    PBKDF from PKCS #12 appendix B
+  * Shamir's secret sharing scheme and Rabin's information dispersal algorithm
+    (IDA)
+  * fast multi-precision integer (bignum) and polynomial operations
+  * finite field arithmetics, including GF(p) and GF(2^n)
+  * prime number generation and verification
+  * useful non-cryptographic algorithms
+      + DEFLATE (RFC 1951) compression/decompression with gzip (RFC 1952) and
+        zlib (RFC 1950) format support
+      + hex, base-32, and base-64 coding/decoding
+      + 32-bit CRC and Adler32 checksum
+  * class wrappers for these operating system features (optional):
+      + high resolution timers on Windows, Unix, and Mac OS
+      + Berkeley and Windows style sockets
+      + Windows named pipes
+      + /dev/random, /dev/urandom, /dev/srandom
+      + Microsoft's CryptGenRandom on Windows
+  * A high level interface for most of the above, using a filter/pipeline
+    metaphor
+  * benchmarks and validation testing
+  * x86, x86-64 (x64), MMX, and SSE2 assembly code for the most commonly used
+    algorithms, with run-time CPU feature detection and code selection
+  * some versions are available in FIPS 140-2 validated form
+
+You are welcome to use it for any purpose without paying me, but see
+License.txt for the fine print.
+
+The following compilers are supported for this release. Please visit
+http://www.cryptopp.com the most up to date build instructions and porting notes.
+
+  * MSVC 6.0 - 2008
+  * GCC 3.3 - 4.3
+  * C++Builder 2009
+  * Intel C++ Compiler 9 - 11
+  * Sun Studio 12 (CC 5.9)
+
+*** Important Usage Notes ***
+
+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.
+
+*** MSVC-Specific Information ***
+
+On Windows, Crypto++ can be compiled into 3 forms: a static library
+including all algorithms, a DLL with only FIPS Approved algorithms, and
+a static library with only algorithms not in the DLL.
+(FIPS Approved means Approved according to the FIPS 140-2 standard.)
+The DLL may be used by itself, or it may be used together with the second
+form of the static library. MSVC project files are included to build
+all three forms, and sample applications using each of the three forms
+are also included.
+
+To compile Crypto++ with MSVC, open the "cryptest.dsw" (for MSVC 6 and MSVC .NET 
+2003) or "cryptest.sln" (for MSVC .NET 2005) workspace file and build one or 
+more of the following projects:
+
+cryptdll - This builds the DLL. Please note that if you wish to use Crypto++
+  as a FIPS validated module, you must use a pre-built DLL that has undergone
+  the FIPS validation process instead of building your own.
+dlltest - This builds a sample application that only uses the DLL.
+cryptest Non-DLL-Import Configuration - This builds the full static library
+  along with a full test driver.
+cryptest DLL-Import Configuration - This builds a static library containing
+  only algorithms not in the DLL, along with a full test driver that uses
+  both the DLL and the static library.
+
+To use the Crypto++ DLL in your application, #include "dll.h" before including
+any other Crypto++ header files, and place the DLL in the same directory as
+your .exe file. dll.h includes the line #pragma comment(lib, "cryptopp")
+so you don't have to explicitly list the import library in your project
+settings. To use a static library form of Crypto++, specify it as
+an additional library to link with in your project settings.
+In either case 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.
+
+*** DLL Memory Management ***
+
+Because it's possible for the Crypto++ DLL to delete objects allocated 
+by the calling application, they must use the same C++ memory heap. Three 
+methods are provided to achieve this.
+1.  The calling application can tell Crypto++ what heap to use. This method 
+    is required when the calling application uses a non-standard heap.
+2.  Crypto++ can tell the calling application what heap to use. This method 
+    is required when the calling application uses a statically linked C++ Run 
+    Time Library. (Method 1 does not work in this case because the Crypto++ DLL 
+    is initialized before the calling application's heap is initialized.)
+3.  Crypto++ can automatically use the heap provided by the calling application's 
+    dynamically linked C++ Run Time Library. The calling application must
+    make sure that the dynamically linked C++ Run Time Library is initialized
+    before Crypto++ is loaded. (At this time it is not clear if it is possible
+    to control the order in which DLLs are initialized on Windows 9x machines,
+    so it might be best to avoid using this method.)
+
+When Crypto++ attaches to a new process, it searches all modules loaded 
+into the process space for exported functions "GetNewAndDeleteForCryptoPP" 
+and "SetNewAndDeleteFromCryptoPP". If one of these functions is found, 
+Crypto++ uses methods 1 or 2, respectively, by calling the function. 
+Otherwise, method 3 is used. 
+
+*** GCC-Specific Information ***
+
+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.
+
+*** Documentation and Support ***
+
+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 by visiting
+http://www.weidai.com, but you will probably get a faster response through
+the mailing list.
+
+*** 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 - added known answer test for X9.17 RNG in FIPS 140 power-up self test
+     - submitted to NIST/CSE, but not publicly released
+
+5.02 - changed EDC test to MAC integrity check using HMAC/SHA1
+     - improved performance of integrity check
+     - added blinding to defend against RSA timing attack
+
+5.03 - created DLL version of Crypto++ for FIPS 140-2 validation
+     - fixed vulnerabilities in GetNextIV for CTR and OFB modes
+
+5.0.4 - Removed DES, SHA-256, SHA-384, SHA-512 from DLL
+
+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
+
+5.2 - merged in changes for 5.01 - 5.0.4
+    - added support for using encoding parameters and key derivation parameters
+      with public key encryption (implemented by OAEP and DL/ECIES)
+    - added Camellia, SHACAL-2, Two-Track-MAC, Whirlpool, RIPEMD-320,
+      RIPEMD-128, RIPEMD-256, Base-32 coding, FIPS variant of CFB mode
+    - added ThreadUserTimer for timing thread CPU usage
+    - added option for password-based key derivation functions
+      to iterate until a mimimum elapsed thread CPU time is reached
+    - added option (on by default) for DEFLATE compression to detect
+      uncompressible files and process them more quickly
+    - improved compatibility and performance on 64-bit platforms,
+      including Alpha, IA-64, x86-64, PPC64, Sparc64, and MIPS64
+    - fixed ONE_AND_ZEROS_PADDING to use 0x80 instead 0x01 as padding.
+    - fixed encoding/decoding of PKCS #8 privateKeyInfo to properly
+      handle optional attributes
+
+5.2.1 - fixed bug in the "dlltest" DLL testing program
+      - fixed compiling with STLport using VC .NET
+      - fixed compiling with -fPIC using GCC
+      - fixed compiling with -msse2 on systems without memalign()
+      - fixed inability to instantiate PanamaMAC
+      - fixed problems with inline documentation
+
+5.2.2 - added SHA-224
+      - put SHA-256, SHA-384, SHA-512, RSASSA-PSS into DLL
+      
+5.2.3 - fixed issues with FIPS algorithm test vectors
+      - put RSASSA-ISO into DLL
+
+5.3 - ported to MSVC 2005 with support for x86-64
+    - added defense against AES timing attacks, and more AES test vectors
+    - changed StaticAlgorithmName() of Rijndael to "AES", CTR to "CTR"
+
+5.4 - added Salsa20
+    - updated Whirlpool to version 3.0
+    - ported to GCC 4.1, Sun C++ 5.8, and Borland C++Builder 2006
+
+5.5 - added VMAC and Sosemanuk (with x86-64 and SSE2 assembly)
+    - improved speed of integer arithmetic, AES, SHA-512, Tiger, Salsa20,
+      Whirlpool, and PANAMA cipher using assembly (x86-64, MMX, SSE2)
+    - optimized Camellia and added defense against timing attacks
+    - updated benchmarks code to show cycles per byte and to time key/IV setup
+    - started using OpenMP for increased multi-core speed
+    - enabled GCC optimization flags by default in GNUmakefile
+    - added blinding and computational error checking for RW signing
+    - changed RandomPool, X917RNG, GetNextIV, DSA/NR/ECDSA/ECNR to reduce
+      the risk of reusing random numbers and IVs after virtual machine state
+      rollback
+    - changed default FIPS mode RNG from AutoSeededX917RNG<DES_EDE3> to
+      AutoSeededX917RNG<AES>
+    - fixed PANAMA cipher interface to accept 256-bit key and 256-bit IV
+    - moved MD2, MD4, MD5, PanamaHash, ARC4, WAKE_CFB into the namespace "Weak"
+    - removed HAVAL, MD5-MAC, XMAC
+
+5.5.1 - fixed VMAC validation failure on 32-bit big-endian machines
+
+5.5.2 - ported x64 assembly language code for AES, Salsa20, Sosemanuk, and Panama
+        to MSVC 2005 (using MASM since MSVC doesn't support inline assembly on x64)
+      - fixed Salsa20 initialization crash on non-SSE2 machines
+      - fixed Whirlpool crash on Pentium 2 machines
+      - fixed possible branch prediction analysis (BPA) vulnerability in
+        MontgomeryReduce(), which may affect security of RSA, RW, LUC
+      - fixed link error with MSVC 2003 when using "debug DLL" form of runtime library
+      - fixed crash in SSE2_Add on P4 machines when compiled with 
+        MSVC 6.0 SP5 with Processor Pack
+      - ported to MSVC 2008, GCC 4.2, Sun CC 5.9, Intel C++ Compiler 10.0, 
+        and Borland C++Builder 2007
+
+5.6 - added AuthenticatedSymmetricCipher interface class and Filter wrappers
+    - added CCM, GCM (with SSE2 assembly), EAX, CMAC, XSalsa20, and SEED
+    - added support for variable length IVs
+    - improved AES and SHA-256 speed on x86 and x64
+    - fixed incorrect VMAC computation on message lengths 
+      that are >64 mod 128 (x86 assembly version is not affected)
+    - fixed compiler error in vmac.cpp on x86 with GCC -fPIC
+    - fixed run-time validation error on x86-64 with GCC 4.3.2 -O2
+    - fixed HashFilter bug when putMessage=true
+    - removed WORD64_AVAILABLE; compiler support for 64-bit int is now required
+    - ported to GCC 4.3, C++Builder 2009, Sun CC 5.10, Intel C++ Compiler 11
+
+Written by Wei Dai
new file mode 100644
--- /dev/null
+++ b/cryptopp/config.h
@@ -0,0 +1,455 @@
+#ifndef CRYPTOPP_CONFIG_H
+#define CRYPTOPP_CONFIG_H
+
+// ***************** Important Settings ********************
+
+// define this if running on a big-endian CPU
+#if !defined(IS_LITTLE_ENDIAN) && (defined(__BIG_ENDIAN__) || defined(__sparc) || defined(__sparc__) || defined(__hppa__) || defined(__mips__) || (defined(__MWERKS__) && !defined(__INTEL__)))
+#	define IS_BIG_ENDIAN
+#endif
+
+// define this if running on a little-endian CPU
+// big endian will be assumed if IS_LITTLE_ENDIAN is not defined
+#ifndef IS_BIG_ENDIAN
+#	define IS_LITTLE_ENDIAN
+#endif
+
+// define this if you want to disable all OS-dependent features,
+// such as sockets and OS-provided random number generators
+// #define NO_OS_DEPENDENCE
+
+// Define this to use features provided by Microsoft's CryptoAPI.
+// Currently the only feature used is random number generation.
+// This macro will be ignored if NO_OS_DEPENDENCE is defined.
+#define USE_MS_CRYPTOAPI
+
+// Define this to 1 to enforce the requirement in FIPS 186-2 Change Notice 1 that only 1024 bit moduli be used
+#ifndef DSA_1024_BIT_MODULUS_ONLY
+#	define DSA_1024_BIT_MODULUS_ONLY 1
+#endif
+
+// ***************** Less Important Settings ***************
+
+// define this to retain (as much as possible) old deprecated function and class names
+// #define CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
+
+#define GZIP_OS_CODE 0
+
+// Try this if your CPU has 256K internal cache or a slow multiply instruction
+// and you want a (possibly) faster IDEA implementation using log tables
+// #define IDEA_LARGECACHE
+
+// 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
+
+// set the name of Rijndael cipher, was "Rijndael" before version 5.3
+#define CRYPTOPP_RIJNDAEL_NAME "AES"
+
+// ***************** 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
+
+#ifdef CRYPTOPP_DOXYGEN_PROCESSING
+// Avoid putting "CryptoPP::" in front of everything in Doxygen output
+#	define CryptoPP
+#	define NAMESPACE_BEGIN(x)
+#	define NAMESPACE_END
+// Get Doxygen to generate better documentation for these typedefs
+#	define DOCUMENTED_TYPEDEF(x, y) class y : public x {};
+#else
+#	define NAMESPACE_BEGIN(x) namespace x {
+#	define NAMESPACE_END }
+#	define DOCUMENTED_TYPEDEF(x, y) typedef x y;
+#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__)
+#		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;		// put in global namespace to avoid ambiguity with other byte typedefs
+
+NAMESPACE_BEGIN(CryptoPP)
+
+typedef unsigned short word16;
+typedef unsigned int word32;
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+	typedef unsigned __int64 word64;
+	#define W64LIT(x) x##ui64
+#else
+	typedef unsigned long long word64;
+	#define W64LIT(x) x##ULL
+#endif
+
+// define large word type, used for file offsets and such
+typedef word64 lword;
+const lword LWORD_MAX = W64LIT(0xffffffffffffffff);
+
+#ifdef __GNUC__
+	#define CRYPTOPP_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
+#endif
+
+// define hword, word, and dword. these are used for multiprecision integer arithmetic
+// Intel compiler won't have _umul128 until version 10.0. See http://softwarecommunity.intel.com/isn/Community/en-US/forums/thread/30231625.aspx
+#if (defined(_MSC_VER) && (!defined(__INTEL_COMPILER) || __INTEL_COMPILER >= 1000) && (defined(_M_X64) || defined(_M_IA64))) || (defined(__DECCXX) && defined(__alpha__)) || (defined(__INTEL_COMPILER) && defined(__x86_64__)) || (defined(__SUNPRO_CC) && defined(__x86_64__))
+	typedef word32 hword;
+	typedef word64 word;
+#else
+	#define CRYPTOPP_NATIVE_DWORD_AVAILABLE
+	#if defined(__alpha__) || defined(__ia64__) || defined(_ARCH_PPC64) || defined(__x86_64__) || defined(__mips64) || defined(__sparc64__)
+		#if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !(CRYPTOPP_GCC_VERSION == 40001 && defined(__APPLE__)) && CRYPTOPP_GCC_VERSION >= 30400
+			// GCC 4.0.1 on MacOS X is missing __umodti3 and __udivti3
+			// mode(TI) division broken on amd64 with GCC earlier than GCC 3.4
+			typedef word32 hword;
+			typedef word64 word;
+			typedef __uint128_t dword;
+			typedef __uint128_t word128;
+			#define CRYPTOPP_WORD128_AVAILABLE
+		#else
+			// if we're here, it means we're on a 64-bit CPU but we don't have a way to obtain 128-bit multiplication results
+			typedef word16 hword;
+			typedef word32 word;
+			typedef word64 dword;
+		#endif
+	#else
+		// being here means the native register size is probably 32 bits or less
+		#define CRYPTOPP_BOOL_SLOW_WORD64 1
+		typedef word16 hword;
+		typedef word32 word;
+		typedef word64 dword;
+	#endif
+#endif
+#ifndef CRYPTOPP_BOOL_SLOW_WORD64
+	#define CRYPTOPP_BOOL_SLOW_WORD64 0
+#endif
+
+const unsigned int WORD_SIZE = sizeof(word);
+const unsigned int WORD_BITS = WORD_SIZE * 8;
+
+NAMESPACE_END
+
+#ifndef CRYPTOPP_L1_CACHE_LINE_SIZE
+	// This should be a lower bound on the L1 cache line size. It's used for defense against timing attacks.
+	#if defined(_M_X64) || defined(__x86_64__)
+		#define CRYPTOPP_L1_CACHE_LINE_SIZE 64
+	#else
+		// L1 cache line size is 32 on Pentium III and earlier
+		#define CRYPTOPP_L1_CACHE_LINE_SIZE 32
+	#endif
+#endif
+
+#if defined(_MSC_VER)
+	#if _MSC_VER == 1200
+		#include <malloc.h>
+	#endif
+	#if _MSC_VER > 1200 || defined(_mm_free)
+		#define CRYPTOPP_MSVC6PP_OR_LATER		// VC 6 processor pack or later
+	#else
+		#define CRYPTOPP_MSVC6_NO_PP			// VC 6 without processor pack
+	#endif
+#endif
+
+#ifndef CRYPTOPP_ALIGN_DATA
+	#if defined(CRYPTOPP_MSVC6PP_OR_LATER)
+		#define CRYPTOPP_ALIGN_DATA(x) __declspec(align(x))
+	#elif defined(__GNUC__)
+		#define CRYPTOPP_ALIGN_DATA(x) __attribute__((aligned(x)))
+	#else
+		#define CRYPTOPP_ALIGN_DATA(x)
+	#endif
+#endif
+
+#ifndef CRYPTOPP_SECTION_ALIGN16
+	#if defined(__GNUC__) && !defined(__APPLE__)
+		// the alignment attribute doesn't seem to work without this section attribute when -fdata-sections is turned on
+		#define CRYPTOPP_SECTION_ALIGN16 __attribute__((section ("CryptoPP_Align16")))
+	#else
+		#define CRYPTOPP_SECTION_ALIGN16
+	#endif
+#endif
+
+#if defined(_MSC_VER) || defined(__fastcall)
+	#define CRYPTOPP_FASTCALL __fastcall
+#else
+	#define CRYPTOPP_FASTCALL
+#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
+
+// VC60 workaround: can't cast unsigned __int64 to float or double
+#if defined(_MSC_VER) && !defined(CRYPTOPP_MSVC6PP_OR_LATER)
+#define CRYPTOPP_VC6_INT64 (__int64)
+#else
+#define CRYPTOPP_VC6_INT64
+#endif
+
+#ifdef _MSC_VER
+#define CRYPTOPP_NO_VTABLE __declspec(novtable)
+#else
+#define CRYPTOPP_NO_VTABLE
+#endif
+
+#ifdef _MSC_VER
+	// 4231: nonstandard extension used : 'extern' before template explicit instantiation
+	// 4250: dominance
+	// 4251: member needs to have dll-interface
+	// 4275: base needs to have dll-interface
+	// 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
+	// 4910: '__declspec(dllexport)' and 'extern' are incompatible on an explicit instantiation
+#	pragma warning(disable: 4231 4250 4251 4275 4660 4661 4786 4355 4910)
+#endif
+
+#ifdef __BORLANDC__
+// 8037: non-const function called for const object. needed to work around BCB2006 bug
+#	pragma warn -8037
+#endif
+
+#if (defined(_MSC_VER) && _MSC_VER <= 1300) || defined(__MWERKS__) || defined(_STLPORT_VERSION)
+#define CRYPTOPP_DISABLE_UNCAUGHT_EXCEPTION
+#endif
+
+#ifndef CRYPTOPP_DISABLE_UNCAUGHT_EXCEPTION
+#define CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE
+#endif
+
+#ifdef CRYPTOPP_DISABLE_X86ASM		// for backwards compatibility: this macro had both meanings
+#define CRYPTOPP_DISABLE_ASM
+#define CRYPTOPP_DISABLE_SSE2
+#endif
+
+#if !defined(CRYPTOPP_DISABLE_ASM) && ((defined(_MSC_VER) && defined(_M_IX86)) || (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))))
+	#define CRYPTOPP_X86_ASM_AVAILABLE
+
+	#if !defined(CRYPTOPP_DISABLE_SSE2) && (defined(CRYPTOPP_MSVC6PP_OR_LATER) || CRYPTOPP_GCC_VERSION >= 30300)
+		#define CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE 1
+	#else
+		#define CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE 0
+	#endif
+
+	// SSSE3 was actually introduced in GNU as 2.17, which was released 6/23/2006, but we can't tell what version of binutils is installed.
+	// GCC 4.1.2 was released on 2/13/2007, so we'll use that as a proxy for the binutils version.
+	#if !defined(CRYPTOPP_DISABLE_SSSE3) && (_MSC_VER >= 1400 || CRYPTOPP_GCC_VERSION >= 40102)
+		#define CRYPTOPP_BOOL_SSSE3_ASM_AVAILABLE 1
+	#else
+		#define CRYPTOPP_BOOL_SSSE3_ASM_AVAILABLE 0
+	#endif
+#endif
+
+#if !defined(CRYPTOPP_DISABLE_ASM) && defined(_MSC_VER) && defined(_M_X64)
+	#define CRYPTOPP_X64_MASM_AVAILABLE
+#endif
+
+#if !defined(CRYPTOPP_DISABLE_ASM) && defined(__GNUC__) && defined(__x86_64__)
+	#define CRYPTOPP_X64_ASM_AVAILABLE
+#endif
+
+#if !defined(CRYPTOPP_DISABLE_SSE2) && (defined(CRYPTOPP_MSVC6PP_OR_LATER) || defined(__SSE2__))
+	#define CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE 1
+#else
+	#define CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE 0
+#endif
+
+#if CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE || CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE)
+	#define CRYPTOPP_BOOL_ALIGN16_ENABLED 1
+#else
+	#define CRYPTOPP_BOOL_ALIGN16_ENABLED 0
+#endif
+
+// how to allocate 16-byte aligned memory (for SSE2)
+#if defined(CRYPTOPP_MSVC6PP_OR_LATER)
+	#define CRYPTOPP_MM_MALLOC_AVAILABLE
+#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
+	#define CRYPTOPP_MALLOC_ALIGNMENT_IS_16
+#elif defined(__linux__) || defined(__sun__) || defined(__CYGWIN__)
+	#define CRYPTOPP_MEMALIGN_AVAILABLE
+#else
+	#define CRYPTOPP_NO_ALIGNED_ALLOC
+#endif
+
+// how to disable inlining
+#if defined(_MSC_VER) && _MSC_VER >= 1300
+#	define CRYPTOPP_NOINLINE_DOTDOTDOT
+#	define CRYPTOPP_NOINLINE __declspec(noinline)
+#elif defined(__GNUC__)
+#	define CRYPTOPP_NOINLINE_DOTDOTDOT
+#	define CRYPTOPP_NOINLINE __attribute__((noinline))
+#else
+#	define CRYPTOPP_NOINLINE_DOTDOTDOT ...
+#	define CRYPTOPP_NOINLINE 
+#endif
+
+// how to declare class constants
+#if (defined(_MSC_VER) && _MSC_VER <= 1300) || defined(__INTEL_COMPILER)
+#	define CRYPTOPP_CONSTANT(x) enum {x};
+#else
+#	define CRYPTOPP_CONSTANT(x) static const int x;
+#endif
+
+#if defined(_M_X64) || defined(__x86_64__)
+	#define CRYPTOPP_BOOL_X64 1
+#else
+	#define CRYPTOPP_BOOL_X64 0
+#endif
+
+// see http://predef.sourceforge.net/prearch.html
+#if defined(_M_IX86) || defined(__i386__) || defined(__i386) || defined(_X86_) || defined(__I86__) || defined(__INTEL__)
+	#define CRYPTOPP_BOOL_X86 1
+#else
+	#define CRYPTOPP_BOOL_X86 0
+#endif
+
+#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X86 || defined(__powerpc__)
+	#define CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
+#endif
+
+#define CRYPTOPP_VERSION 560
+
+// ***************** 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__) || defined(__sun)
+#define CRYPTOPP_UNIX_AVAILABLE
+#endif
+
+#if defined(CRYPTOPP_WIN32_AVAILABLE) || defined(CRYPTOPP_UNIX_AVAILABLE)
+#	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(HIGHRES_TIMER_AVAILABLE) && 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
+
+#if defined(CRYPTOPP_UNIX_AVAILABLE) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
+#	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
+
+// ***************** DLL related ********************
+
+#ifdef CRYPTOPP_WIN32_AVAILABLE
+
+#ifdef CRYPTOPP_EXPORTS
+#define CRYPTOPP_IS_DLL
+#define CRYPTOPP_DLL __declspec(dllexport)
+#elif defined(CRYPTOPP_IMPORTS)
+#define CRYPTOPP_IS_DLL
+#define CRYPTOPP_DLL __declspec(dllimport)
+#else
+#define CRYPTOPP_DLL
+#endif
+
+#define CRYPTOPP_API __cdecl
+
+#else	// CRYPTOPP_WIN32_AVAILABLE
+
+#define CRYPTOPP_DLL
+#define CRYPTOPP_API
+
+#endif	// CRYPTOPP_WIN32_AVAILABLE
+
+#if defined(__MWERKS__)
+#define CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS extern class CRYPTOPP_DLL
+#elif defined(__BORLANDC__) || defined(__SUNPRO_CC)
+#define CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS template class CRYPTOPP_DLL
+#else
+#define CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS extern template class CRYPTOPP_DLL
+#endif
+
+#if defined(CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES) && !defined(CRYPTOPP_IMPORTS)
+#define CRYPTOPP_DLL_TEMPLATE_CLASS template class CRYPTOPP_DLL
+#else
+#define CRYPTOPP_DLL_TEMPLATE_CLASS CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS
+#endif
+
+#if defined(__MWERKS__)
+#define CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS extern class
+#elif defined(__BORLANDC__) || defined(__SUNPRO_CC)
+#define CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS template class
+#else
+#define CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS extern template class
+#endif
+
+#if defined(CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES) && !defined(CRYPTOPP_EXPORTS)
+#define CRYPTOPP_STATIC_TEMPLATE_CLASS template class
+#else
+#define CRYPTOPP_STATIC_TEMPLATE_CLASS CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS
+#endif
+
+#endif
new file mode 100644
--- /dev/null
+++ b/cryptopp/cpu.cpp
@@ -0,0 +1,199 @@
+// cpu.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "cpu.h"
+#include "misc.h"
+#include <algorithm>
+
+#ifdef __GNUC__
+#include <signal.h>
+#include <setjmp.h>
+#endif
+
+#ifdef CRYPTOPP_MSVC6PP_OR_LATER
+#include <emmintrin.h>
+#endif
+
+NAMESPACE_BEGIN(CryptoPP)
+
+#ifdef CRYPTOPP_X86_ASM_AVAILABLE
+
+#ifndef _MSC_VER
+typedef void (*SigHandler)(int);
+
+static jmp_buf s_jmpNoCPUID;
+static void SigIllHandlerCPUID(int)
+{
+	longjmp(s_jmpNoCPUID, 1);
+}
+#endif
+
+bool CpuId(word32 input, word32 *output)
+{
+#ifdef _MSC_VER
+    __try
+	{
+		__asm
+		{
+			mov eax, input
+			cpuid
+			mov edi, output
+			mov [edi], eax
+			mov [edi+4], ebx
+			mov [edi+8], ecx
+			mov [edi+12], edx
+		}
+	}
+    __except (1)
+	{
+		return false;
+    }
+	return true;
+#else
+	SigHandler oldHandler = signal(SIGILL, SigIllHandlerCPUID);
+	if (oldHandler == SIG_ERR)
+		return false;
+
+	bool result = true;
+	if (setjmp(s_jmpNoCPUID))
+		result = false;
+	else
+	{
+		__asm__
+		(
+			// save ebx in case -fPIC is being used
+#if CRYPTOPP_BOOL_X86
+			"push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx"
+#else
+			"pushq %%rbx; cpuid; mov %%ebx, %%edi; popq %%rbx"
+#endif
+			: "=a" (output[0]), "=D" (output[1]), "=c" (output[2]), "=d" (output[3])
+			: "a" (input)
+		);
+	}
+
+	signal(SIGILL, oldHandler);
+	return result;
+#endif
+}
+
+#ifndef _MSC_VER
+static jmp_buf s_jmpNoSSE2;
+static void SigIllHandlerSSE2(int)
+{
+	longjmp(s_jmpNoSSE2, 1);
+}
+#endif
+
+#elif _MSC_VER >= 1400 && CRYPTOPP_BOOL_X64
+
+bool CpuId(word32 input, word32 *output)
+{
+	__cpuid((int *)output, input);
+	return true;
+}
+
+#endif
+
+#ifdef CRYPTOPP_CPUID_AVAILABLE
+
+static bool TrySSE2()
+{
+#if CRYPTOPP_BOOL_X64
+	return true;
+#elif defined(_MSC_VER)
+    __try
+	{
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+        AS2(por xmm0, xmm0)        // executing SSE2 instruction
+#elif CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE
+		__mm128i x = _mm_setzero_si128();
+		return _mm_cvtsi128_si32(x) == 0;
+#endif
+	}
+    __except (1)
+	{
+		return false;
+    }
+	return true;
+#elif defined(__GNUC__)
+	SigHandler oldHandler = signal(SIGILL, SigIllHandlerSSE2);
+	if (oldHandler == SIG_ERR)
+		return false;
+
+	bool result = true;
+	if (setjmp(s_jmpNoSSE2))
+		result = false;
+	else
+	{
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+		__asm __volatile ("por %xmm0, %xmm0");
+#elif CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE
+		__mm128i x = _mm_setzero_si128();
+		result = _mm_cvtsi128_si32(x) == 0;
+#endif
+	}
+
+	signal(SIGILL, oldHandler);
+	return result;
+#else
+	return false;
+#endif
+}
+
+bool g_x86DetectionDone = false;
+bool g_hasISSE = false, g_hasSSE2 = false, g_hasSSSE3 = false, g_hasMMX = false, g_isP4 = false;
+word32 g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
+
+void DetectX86Features()
+{
+	word32 cpuid[4], cpuid1[4];
+	if (!CpuId(0, cpuid))
+		return;
+	if (!CpuId(1, cpuid1))
+		return;
+
+	g_hasMMX = (cpuid1[3] & (1 << 23)) != 0;
+	if ((cpuid1[3] & (1 << 26)) != 0)
+		g_hasSSE2 = TrySSE2();
+	g_hasSSSE3 = g_hasSSE2 && (cpuid1[2] & (1<<9));
+
+	if ((cpuid1[3] & (1 << 25)) != 0)
+		g_hasISSE = true;
+	else
+	{
+		word32 cpuid2[4];
+		CpuId(0x080000000, cpuid2);
+		if (cpuid2[0] >= 0x080000001)
+		{
+			CpuId(0x080000001, cpuid2);
+			g_hasISSE = (cpuid2[3] & (1 << 22)) != 0;
+		}
+	}
+
+	std::swap(cpuid[2], cpuid[3]);
+	if (memcmp(cpuid+1, "GenuineIntel", 12) == 0)
+	{
+		g_isP4 = ((cpuid1[0] >> 8) & 0xf) == 0xf;
+		g_cacheLineSize = 8 * GETBYTE(cpuid1[1], 1);
+	}
+	else if (memcmp(cpuid+1, "AuthenticAMD", 12) == 0)
+	{
+		CpuId(0x80000005, cpuid);
+		g_cacheLineSize = GETBYTE(cpuid[2], 0);
+	}
+
+	if (!g_cacheLineSize)
+		g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
+
+	g_x86DetectionDone = true;
+}
+
+#endif
+
+NAMESPACE_END
+
+#endif
new file mode 100644
--- /dev/null
+++ b/cryptopp/cpu.h
@@ -0,0 +1,263 @@
+#ifndef CRYPTOPP_CPU_H
+#define CRYPTOPP_CPU_H
+
+#ifdef CRYPTOPP_GENERATE_X64_MASM
+
+#define CRYPTOPP_X86_ASM_AVAILABLE
+#define CRYPTOPP_BOOL_X64 1
+#define CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE 1
+#define NAMESPACE_END
+
+#else
+
+#include "config.h"
+
+#ifdef CRYPTOPP_MSVC6PP_OR_LATER
+	#include <emmintrin.h>
+#endif
+
+NAMESPACE_BEGIN(CryptoPP)
+
+#if defined(CRYPTOPP_X86_ASM_AVAILABLE) || (_MSC_VER >= 1400 && CRYPTOPP_BOOL_X64)
+
+#define CRYPTOPP_CPUID_AVAILABLE
+
+// these should not be used directly
+extern CRYPTOPP_DLL bool g_x86DetectionDone;
+extern CRYPTOPP_DLL bool g_hasSSE2;
+extern CRYPTOPP_DLL bool g_hasISSE;
+extern CRYPTOPP_DLL bool g_hasMMX;
+extern CRYPTOPP_DLL bool g_hasSSSE3;
+extern CRYPTOPP_DLL bool g_isP4;
+extern CRYPTOPP_DLL word32 g_cacheLineSize;
+CRYPTOPP_DLL void CRYPTOPP_API DetectX86Features();
+
+CRYPTOPP_DLL bool CRYPTOPP_API CpuId(word32 input, word32 *output);
+
+#if CRYPTOPP_BOOL_X64
+inline bool HasSSE2()	{return true;}
+inline bool HasISSE()	{return true;}
+inline bool HasMMX()	{return true;}
+#else
+
+inline bool HasSSE2()
+{
+	if (!g_x86DetectionDone)
+		DetectX86Features();
+	return g_hasSSE2;
+}
+
+inline bool HasISSE()
+{
+	if (!g_x86DetectionDone)
+		DetectX86Features();
+	return g_hasISSE;
+}
+
+inline bool HasMMX()
+{
+	if (!g_x86DetectionDone)
+		DetectX86Features();
+	return g_hasMMX;
+}
+
+#endif
+
+inline bool HasSSSE3()
+{
+	if (!g_x86DetectionDone)
+		DetectX86Features();
+	return g_hasSSSE3;
+}
+
+inline bool IsP4()
+{
+	if (!g_x86DetectionDone)
+		DetectX86Features();
+	return g_isP4;
+}
+
+inline int GetCacheLineSize()
+{
+	if (!g_x86DetectionDone)
+		DetectX86Features();
+	return g_cacheLineSize;
+}
+
+#else
+
+inline int GetCacheLineSize()
+{
+	return CRYPTOPP_L1_CACHE_LINE_SIZE;
+}
+
+inline bool HasSSSE3()	{return false;}
+inline bool IsP4()		{return false;}
+
+// assume MMX and SSE2 if intrinsics are enabled
+#if CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE || CRYPTOPP_BOOL_X64
+inline bool HasSSE2()	{return true;}
+inline bool HasISSE()	{return true;}
+inline bool HasMMX()	{return true;}
+#else
+inline bool HasSSE2()	{return false;}
+inline bool HasISSE()	{return false;}
+inline bool HasMMX()	{return false;}
+#endif
+
+#endif		// #ifdef CRYPTOPP_X86_ASM_AVAILABLE || _MSC_VER >= 1400
+
+#endif
+
+#ifdef CRYPTOPP_GENERATE_X64_MASM
+	#define AS1(x) x*newline*
+	#define AS2(x, y) x, y*newline*
+	#define AS3(x, y, z) x, y, z*newline*
+	#define ASS(x, y, a, b, c, d) x, y, a*64+b*16+c*4+d*newline*
+	#define ASL(x) label##x:*newline*
+	#define ASJ(x, y, z) x label##y*newline*
+	#define ASC(x, y) x label##y*newline*
+	#define AS_HEX(y) 0##y##h
+#elif defined(__GNUC__)
+	// define these in two steps to allow arguments to be expanded
+	#define GNU_AS1(x) #x ";"
+	#define GNU_AS2(x, y) #x ", " #y ";"
+	#define GNU_AS3(x, y, z) #x ", " #y ", " #z ";"
+	#define GNU_ASL(x) "\n" #x ":"
+	#define GNU_ASJ(x, y, z) #x " " #y #z ";"
+	#define AS1(x) GNU_AS1(x)
+	#define AS2(x, y) GNU_AS2(x, y)
+	#define AS3(x, y, z) GNU_AS3(x, y, z)
+	#define ASS(x, y, a, b, c, d) #x ", " #y ", " #a "*64+" #b "*16+" #c "*4+" #d ";"
+	#define ASL(x) GNU_ASL(x)
+	#define ASJ(x, y, z) GNU_ASJ(x, y, z)
+	#define ASC(x, y) #x " " #y ";"
+	#define CRYPTOPP_NAKED
+	#define AS_HEX(y) 0x##y
+#else
+	#define AS1(x) __asm {x}
+	#define AS2(x, y) __asm {x, y}
+	#define AS3(x, y, z) __asm {x, y, z}
+	#define ASS(x, y, a, b, c, d) __asm {x, y, _MM_SHUFFLE(a, b, c, d)}
+	#define ASL(x) __asm {label##x:}
+	#define ASJ(x, y, z) __asm {x label##y}
+	#define ASC(x, y) __asm {x label##y}
+	#define CRYPTOPP_NAKED __declspec(naked)
+	#define AS_HEX(y) 0x##y
+#endif
+
+#define IF0(y)
+#define IF1(y) y
+
+#ifdef CRYPTOPP_GENERATE_X64_MASM
+#define ASM_MOD(x, y) ((x) MOD (y))
+#define XMMWORD_PTR XMMWORD PTR
+#else
+// GNU assembler doesn't seem to have mod operator
+#define ASM_MOD(x, y) ((x)-((x)/(y))*(y))
+// GAS 2.15 doesn't support XMMWORD PTR. it seems necessary only for MASM
+#define XMMWORD_PTR
+#endif
+
+#if CRYPTOPP_BOOL_X86
+	#define AS_REG_1 ecx
+	#define AS_REG_2 edx
+	#define AS_REG_3 esi
+	#define AS_REG_4 edi
+	#define AS_REG_5 eax
+	#define AS_REG_6 ebx
+	#define AS_REG_7 ebp
+	#define AS_REG_1d ecx
+	#define AS_REG_2d edx
+	#define AS_REG_3d esi
+	#define AS_REG_4d edi
+	#define AS_REG_5d eax
+	#define AS_REG_6d ebx
+	#define AS_REG_7d ebp
+	#define WORD_SZ 4
+	#define WORD_REG(x)	e##x
+	#define WORD_PTR DWORD PTR
+	#define AS_PUSH_IF86(x) AS1(push e##x)
+	#define AS_POP_IF86(x) AS1(pop e##x)
+	#define AS_JCXZ jecxz
+#elif CRYPTOPP_BOOL_X64
+	#ifdef CRYPTOPP_GENERATE_X64_MASM
+		#define AS_REG_1 rcx
+		#define AS_REG_2 rdx
+		#define AS_REG_3 r8
+		#define AS_REG_4 r9
+		#define AS_REG_5 rax
+		#define AS_REG_6 r10
+		#define AS_REG_7 r11
+		#define AS_REG_1d ecx
+		#define AS_REG_2d edx
+		#define AS_REG_3d r8d
+		#define AS_REG_4d r9d
+		#define AS_REG_5d eax
+		#define AS_REG_6d r10d
+		#define AS_REG_7d r11d
+	#else
+		#define AS_REG_1 rdi
+		#define AS_REG_2 rsi
+		#define AS_REG_3 rdx
+		#define AS_REG_4 rcx
+		#define AS_REG_5 r8
+		#define AS_REG_6 r9
+		#define AS_REG_7 r10
+		#define AS_REG_1d edi
+		#define AS_REG_2d esi
+		#define AS_REG_3d edx
+		#define AS_REG_4d ecx
+		#define AS_REG_5d r8d
+		#define AS_REG_6d r9d
+		#define AS_REG_7d r10d
+	#endif
+	#define WORD_SZ 8
+	#define WORD_REG(x)	r##x
+	#define WORD_PTR QWORD PTR
+	#define AS_PUSH_IF86(x)
+	#define AS_POP_IF86(x)
+	#define AS_JCXZ jrcxz
+#endif
+
+// helper macro for stream cipher output
+#define AS_XMM_OUTPUT4(labelPrefix, inputPtr, outputPtr, x0, x1, x2, x3, t, p0, p1, p2, p3, increment)\
+	AS2(	test	inputPtr, inputPtr)\
+	ASC(	jz,		labelPrefix##3)\
+	AS2(	test	inputPtr, 15)\
+	ASC(	jnz,	labelPrefix##7)\
+	AS2(	pxor	xmm##x0, [inputPtr+p0*16])\
+	AS2(	pxor	xmm##x1, [inputPtr+p1*16])\
+	AS2(	pxor	xmm##x2, [inputPtr+p2*16])\
+	AS2(	pxor	xmm##x3, [inputPtr+p3*16])\
+	AS2(	add		inputPtr, increment*16)\
+	ASC(	jmp,	labelPrefix##3)\
+	ASL(labelPrefix##7)\
+	AS2(	movdqu	xmm##t, [inputPtr+p0*16])\
+	AS2(	pxor	xmm##x0, xmm##t)\
+	AS2(	movdqu	xmm##t, [inputPtr+p1*16])\
+	AS2(	pxor	xmm##x1, xmm##t)\
+	AS2(	movdqu	xmm##t, [inputPtr+p2*16])\
+	AS2(	pxor	xmm##x2, xmm##t)\
+	AS2(	movdqu	xmm##t, [inputPtr+p3*16])\
+	AS2(	pxor	xmm##x3, xmm##t)\
+	AS2(	add		inputPtr, increment*16)\
+	ASL(labelPrefix##3)\
+	AS2(	test	outputPtr, 15)\
+	ASC(	jnz,	labelPrefix##8)\
+	AS2(	movdqa	[outputPtr+p0*16], xmm##x0)\
+	AS2(	movdqa	[outputPtr+p1*16], xmm##x1)\
+	AS2(	movdqa	[outputPtr+p2*16], xmm##x2)\
+	AS2(	movdqa	[outputPtr+p3*16], xmm##x3)\
+	ASC(	jmp,	labelPrefix##9)\
+	ASL(labelPrefix##8)\
+	AS2(	movdqu	[outputPtr+p0*16], xmm##x0)\
+	AS2(	movdqu	[outputPtr+p1*16], xmm##x1)\
+	AS2(	movdqu	[outputPtr+p2*16], xmm##x2)\
+	AS2(	movdqu	[outputPtr+p3*16], xmm##x3)\
+	ASL(labelPrefix##9)\
+	AS2(	add		outputPtr, increment*16)
+
+NAMESPACE_END
+
+#endif
new file mode 100644
--- /dev/null
+++ b/cryptopp/cryptlib.h
@@ -0,0 +1,1668 @@
+// cryptlib.h - written and placed in the public domain by Wei Dai
+/*! \file
+ 	This file contains the declarations for the abstract base
+	classes that provide a uniform interface to this library.
+*/
+
+/*!	\mainpage Crypto++ Library 5.6.0 API Reference
+<dl>
+<dt>Abstract Base Classes<dd>
+	cryptlib.h
+<dt>Authenticated Encryption<dd>
+	AuthenticatedSymmetricCipherDocumentation
+<dt>Symmetric Ciphers<dd>
+	SymmetricCipherDocumentation
+<dt>Hash Functions<dd>
+	SHA1, SHA224, SHA256, SHA384, SHA512, Tiger, Whirlpool, RIPEMD160, RIPEMD320, RIPEMD128, RIPEMD256, Weak1::MD2, Weak1::MD4, Weak1::MD5
+<dt>Non-Cryptographic Checksums<dd>
+	CRC32, Adler32
+<dt>Message Authentication Codes<dd>
+	VMAC, HMAC, CBC_MAC, CMAC, DMAC, TTMAC, GCM (GMAC)
+<dt>Random Number Generators<dd>
+	NullRNG(), LC_RNG, RandomPool, BlockingRng, NonblockingRng, AutoSeededRandomPool, AutoSeededX917RNG, DefaultAutoSeededRNG
+<dt>Password-based Cryptography<dd>
+	PasswordBasedKeyDerivationFunction
+<dt>Public Key Cryptosystems<dd>
+	DLIES, ECIES, LUCES, RSAES, RabinES, LUC_IES
+<dt>Public Key Signature Schemes<dd>
+	DSA, GDSA, ECDSA, NR, ECNR, LUCSS, RSASS, RSASS_ISO, RabinSS, RWSS, ESIGN
+<dt>Key Agreement<dd>
+	#DH, DH2, #MQV, ECDH, ECMQV, XTR_DH
+<dt>Algebraic Structures<dd>
+	Integer, PolynomialMod2, PolynomialOver, RingOfPolynomialsOver,
+	ModularArithmetic, MontgomeryRepresentation, GFP2_ONB,
+	GF2NP, GF256, GF2_32, EC2N, ECP
+<dt>Secret Sharing and Information Dispersal<dd>
+	SecretSharing, SecretRecovery, InformationDispersal, InformationRecovery
+<dt>Compression<dd>
+	Deflator, Inflator, Gzip, Gunzip, ZlibCompressor, ZlibDecompressor
+<dt>Input Source Classes<dd>
+	StringSource, ArraySource, FileSource, SocketSource, WindowsPipeSource, RandomNumberSource
+<dt>Output Sink Classes<dd>
+	StringSinkTemplate, ArraySink, FileSink, SocketSink, WindowsPipeSink, RandomNumberSink
+<dt>Filter Wrappers<dd>
+	StreamTransformationFilter, HashFilter, HashVerificationFilter, SignerFilter, SignatureVerificationFilter
+<dt>Binary to Text Encoders and Decoders<dd>
+	HexEncoder, HexDecoder, Base64Encoder, Base64Decoder, Base32Encoder, Base32Decoder
+<dt>Wrappers for OS features<dd>
+	Timer, Socket, WindowsHandle, ThreadLocalStorage, ThreadUserTimer
+<dt>FIPS 140 related<dd>
+	fips140.h
+</dl>
+
+In the FIPS 140-2 validated DLL version of Crypto++, only the following implementation class are available.
+<dl>
+<dt>Block Ciphers<dd>
+	AES, DES_EDE2, DES_EDE3, SKIPJACK
+<dt>Cipher Modes (replace template parameter BC with one of the block ciphers above)<dd>
+	ECB_Mode\<BC\>, CTR_Mode\<BC\>, CBC_Mode\<BC\>, CFB_FIPS_Mode\<BC\>, OFB_Mode\<BC\>
+<dt>Hash Functions<dd>
+	SHA1, SHA224, SHA256, SHA384, SHA512
+<dt>Public Key Signature Schemes (replace template parameter H with one of the hash functions above)<dd>
+	RSASS\<PKCS1v15, H\>, RSASS\<PSS, H\>, RSASS_ISO\<H\>, RWSS\<P1363_EMSA2, H\>, DSA, ECDSA\<ECP, H\>, ECDSA\<EC2N, H\>
+<dt>Message Authentication Codes (replace template parameter H with one of the hash functions above)<dd>
+	HMAC\<H\>, CBC_MAC\<DES_EDE2\>, CBC_MAC\<DES_EDE3\>
+<dt>Random Number Generators<dd>
+	DefaultAutoSeededRNG (AutoSeededX917RNG\<AES\>)
+<dt>Key Agreement<dd>
+	#DH
+<dt>Public Key Cryptosystems<dd>
+	RSAES\<OAEP\<SHA1\> \>
+</dl>
+
+<p>This reference manual is a work in progress. Some classes are still lacking detailed descriptions.
+<p>Click <a href="CryptoPPRef.zip">here</a> to download a zip archive containing this manual.
+<p>Thanks to Ryan Phillips for providing the Doxygen configuration file
+and getting me started with this manual.
+*/
+
+#ifndef CRYPTOPP_CRYPTLIB_H
+#define CRYPTOPP_CRYPTLIB_H
+
+#include "config.h"
+#include "stdcpp.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+// forward declarations
+class Integer;
+class RandomNumberGenerator;
+class BufferedTransformation;
+
+//! used to specify a direction for a cipher to operate in (encrypt or decrypt)
+enum CipherDir {ENCRYPTION, DECRYPTION};
+
+//! used to represent infinite time
+const unsigned long INFINITE_TIME = ULONG_MAX;
+
+// VC60 workaround: using enums as template parameters causes problems
+template <typename ENUM_TYPE, int VALUE>
+struct EnumToType
+{
+	static ENUM_TYPE ToEnum() {return (ENUM_TYPE)VALUE;}
+};
+
+enum ByteOrder {LITTLE_ENDIAN_ORDER = 0, BIG_ENDIAN_ORDER = 1};
+typedef EnumToType<ByteOrder, LITTLE_ENDIAN_ORDER> LittleEndian;
+typedef EnumToType<ByteOrder, BIG_ENDIAN_ORDER> BigEndian;
+
+//! base class for all exceptions thrown by Crypto++
+class CRYPTOPP_DLL Exception : public std::exception
+{
+public:
+	//! error types
+	enum ErrorType {
+		//! a method is not implemented
+		NOT_IMPLEMENTED,
+		//! invalid function argument
+		INVALID_ARGUMENT,
+		//! BufferedTransformation received a Flush(true) signal but can't flush buffers
+		CANNOT_FLUSH,
+		//! data integerity check (such as CRC or MAC) failed
+		DATA_INTEGRITY_CHECK_FAILED,
+		//! received input data that doesn't conform to expected format
+		INVALID_DATA_FORMAT,
+		//! error reading from input device or writing to output device
+		IO_ERROR,
+		//! some error not belong to any of the above categories
+		OTHER_ERROR
+	};
+
+	explicit Exception(ErrorType errorType, const std::string &s) : m_errorType(errorType), m_what(s) {}
+	virtual ~Exception() throw() {}
+	const char *what() const throw() {return (m_what.c_str());}
+	const std::string &GetWhat() const {return m_what;}
+	void SetWhat(const std::string &s) {m_what = s;}
+	ErrorType GetErrorType() const {return m_errorType;}
+	void SetErrorType(ErrorType errorType) {m_errorType = errorType;}
+
+private:
+	ErrorType m_errorType;
+	std::string m_what;
+};
+
+//! exception thrown when an invalid argument is detected
+class CRYPTOPP_DLL InvalidArgument : public Exception
+{
+public:
+	explicit InvalidArgument(const std::string &s) : Exception(INVALID_ARGUMENT, s) {}
+};
+
+//! exception thrown when input data is received that doesn't conform to expected format
+class CRYPTOPP_DLL InvalidDataFormat : public Exception
+{
+public:
+	explicit InvalidDataFormat(const std::string &s) : Exception(INVALID_DATA_FORMAT, s) {}
+};
+
+//! exception thrown by decryption filters when trying to decrypt an invalid ciphertext
+class CRYPTOPP_DLL InvalidCiphertext : public InvalidDataFormat
+{
+public:
+	explicit InvalidCiphertext(const std::string &s) : InvalidDataFormat(s) {}
+};
+
+//! exception thrown by a class if a non-implemented method is called
+class CRYPTOPP_DLL NotImplemented : public Exception
+{
+public:
+	explicit NotImplemented(const std::string &s) : Exception(NOT_IMPLEMENTED, s) {}
+};
+
+//! exception thrown by a class when Flush(true) is called but it can't completely flush its buffers
+class CRYPTOPP_DLL CannotFlush : public Exception
+{
+public:
+	explicit CannotFlush(const std::string &s) : Exception(CANNOT_FLUSH, s) {}
+};
+
+//! error reported by the operating system
+class CRYPTOPP_DLL OS_Error : public Exception
+{
+public:
+	OS_Error(ErrorType errorType, const std::string &s, const std::string& operation, int errorCode)
+		: Exception(errorType, s), m_operation(operation), m_errorCode(errorCode) {}
+	~OS_Error() throw() {}
+
+	// the operating system API that reported the error
+	const std::string & GetOperation() const {return m_operation;}
+	// the error code return by the operating system
+	int GetErrorCode() const {return m_errorCode;}
+
+protected:
+	std::string m_operation;
+	int m_errorCode;
+};
+
+//! used to return decoding results
+struct CRYPTOPP_DLL DecodingResult
+{
+	explicit DecodingResult() : isValidCoding(false), messageLength(0) {}
+	explicit DecodingResult(size_t len) : isValidCoding(true), messageLength(len) {}
+
+	bool operator==(const DecodingResult &rhs) const {return isValidCoding == rhs.isValidCoding && messageLength == rhs.messageLength;}
+	bool operator!=(const DecodingResult &rhs) const {return !operator==(rhs);}
+
+	bool isValidCoding;
+	size_t messageLength;
+
+#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
+	operator size_t() const {return isValidCoding ? messageLength : 0;}
+#endif
+};
+
+//! interface for retrieving values given their names
+/*! \note This class is used to safely pass a variable number of arbitrarily typed arguments to functions
+	and to read values from keys and crypto parameters.
+	\note To obtain an object that implements NameValuePairs for the purpose of parameter
+	passing, use the MakeParameters() function.
+	\note To get a value from NameValuePairs, you need to know the name and the type of the value. 
+	Call GetValueNames() on a NameValuePairs object to obtain a list of value names that it supports.
+	Then look at the Name namespace documentation to see what the type of each value is, or
+	alternatively, call GetIntValue() with the value name, and if the type is not int, a
+	ValueTypeMismatch exception will be thrown and you can get the actual type from the exception object.
+*/
+class CRYPTOPP_NO_VTABLE NameValuePairs
+{
+public:
+	virtual ~NameValuePairs() {}
+
+	//! exception thrown when trying to retrieve a value using a different type than expected
+	class CRYPTOPP_DLL ValueTypeMismatch : public InvalidArgument
+	{
+	public:
+		ValueTypeMismatch(const std::string &name, const std::type_info &stored, const std::type_info &retrieving)
+			: InvalidArgument("NameValuePairs: type mismatch for '" + name + "', stored '" + stored.name() + "', trying to retrieve '" + retrieving.name() + "'")
+			, m_stored(stored), m_retrieving(retrieving) {}
+
+		const std::type_info & GetStoredTypeInfo() const {return m_stored;}
+		const std::type_info & GetRetrievingTypeInfo() const {return m_retrieving;}
+
+	private:
+		const std::type_info &m_stored;
+		const std::type_info &m_retrieving;
+	};
+
+	//! get a copy of this object or a subobject of it
+	template <class T>
+	bool GetThisObject(T &object) const
+	{
+		return GetValue((std::string("ThisObject:")+typeid(T).name()).c_str(), object);
+	}
+
+	//! get a pointer to this object, as a pointer to T
+	template <class T>
+	bool GetThisPointer(T *&p) const
+	{
+		return GetValue((std::string("ThisPointer:")+typeid(T).name()).c_str(), p);
+	}
+
+	//! get a named value, returns true if the name exists
+	template <class T>
+	bool GetValue(const char *name, T &value) const
+	{
+		return GetVoidValue(name, typeid(T), &value);
+	}
+
+	//! get a named value, returns the default if the name doesn't exist
+	template <class T>
+	T GetValueWithDefault(const char *name, T defaultValue) const
+	{
+		GetValue(name, defaultValue);
+		return defaultValue;
+	}
+
+	//! get a list of value names that can be retrieved
+	CRYPTOPP_DLL std::string GetValueNames() const
+		{std::string result; GetValue("ValueNames", result); return result;}
+
+	//! get a named value with type int
+	/*! used to ensure we don't accidentally try to get an unsigned int
+		or some other type when we mean int (which is the most common case) */
+	CRYPTOPP_DLL bool GetIntValue(const char *name, int &value) const
+		{return GetValue(name, value);}
+
+	//! get a named value with type int, with default
+	CRYPTOPP_DLL int GetIntValueWithDefault(const char *name, int defaultValue) const
+		{return GetValueWithDefault(name, defaultValue);}
+
+	//! used by derived classes to check for type mismatch
+	CRYPTOPP_DLL static void CRYPTOPP_API ThrowIfTypeMismatch(const char *name, const std::type_info &stored, const std::type_info &retrieving)
+		{if (stored != retrieving) throw ValueTypeMismatch(name, stored, retrieving);}
+
+	template <class T>
+	void GetRequiredParameter(const char *className, const char *name, T &value) const
+	{
+		if (!GetValue(name, value))
+			throw InvalidArgument(std::string(className) + ": missing required parameter '" + name + "'");
+	}
+
+	CRYPTOPP_DLL void GetRequiredIntParameter(const char *className, const char *name, int &value) const
+	{
+		if (!GetIntValue(name, value))
+			throw InvalidArgument(std::string(className) + ": missing required parameter '" + name + "'");
+	}
+
+	//! to be implemented by derived classes, users should use one of the above functions instead
+	CRYPTOPP_DLL virtual bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const =0;
+};
+
+//! namespace containing value name definitions
+/*!	value names, types and semantics:
+
+	ThisObject:ClassName (ClassName, copy of this object or a subobject)
+	ThisPointer:ClassName (const ClassName *, pointer to this object or a subobject)
+*/
+DOCUMENTED_NAMESPACE_BEGIN(Name)
+// more names defined in argnames.h
+DOCUMENTED_NAMESPACE_END
+
+//! empty set of name-value pairs
+class CRYPTOPP_DLL NullNameValuePairs : public NameValuePairs
+{
+public:
+	bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const {return false;}
+};
+
+//! _
+extern CRYPTOPP_DLL const NullNameValuePairs g_nullNameValuePairs;
+
+// ********************************************************
+
+//! interface for cloning objects, this is not implemented by most classes yet
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Clonable
+{
+public:
+	virtual ~Clonable() {}
+	//! this is not implemented by most classes yet
+	virtual Clonable* Clone() const {throw NotImplemented("Clone() is not implemented yet.");}	// TODO: make this =0
+};
+
+//! interface for all crypto algorithms
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Algorithm : public Clonable
+{
+public:
+	/*! When FIPS 140-2 compliance is enabled and checkSelfTestStatus == true,
+		this constructor throws SelfTestFailure if the self test hasn't been run or fails. */
+	Algorithm(bool checkSelfTestStatus = true);
+	//! returns name of this algorithm, not universally implemented yet
+	virtual std::string AlgorithmName() const {return "unknown";}
+};
+
+//! keying interface for crypto algorithms that take byte strings as keys
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE SimpleKeyingInterface
+{
+public:
+	virtual ~SimpleKeyingInterface() {}
+
+	//! returns smallest valid key length in bytes */
+	virtual size_t MinKeyLength() const =0;
+	//! returns largest valid key length in bytes */
+	virtual size_t MaxKeyLength() const =0;
+	//! returns default (recommended) key length in bytes */
+	virtual size_t DefaultKeyLength() const =0;
+
+	//! returns the smallest valid key length in bytes that is >= min(n, GetMaxKeyLength())
+	virtual size_t GetValidKeyLength(size_t n) const =0;
+
+	//! returns whether n is a valid key length
+	virtual bool IsValidKeyLength(size_t n) const
+		{return n == GetValidKeyLength(n);}
+
+	//! set or reset the key of this object
+	/*! \param params is used to specify Rounds, BlockSize, etc. */
+	virtual void SetKey(const byte *key, size_t length, const NameValuePairs &params = g_nullNameValuePairs);
+
+	//! calls SetKey() with an NameValuePairs object that just specifies "Rounds"
+	void SetKeyWithRounds(const byte *key, size_t length, int rounds);
+
+	//! calls SetKey() with an NameValuePairs object that just specifies "IV"
+	void SetKeyWithIV(const byte *key, size_t length, const byte *iv, size_t ivLength);
+
+	//! calls SetKey() with an NameValuePairs object that just specifies "IV"
+	void SetKeyWithIV(const byte *key, size_t length, const byte *iv)
+		{SetKeyWithIV(key, length, iv, IVSize());}
+
+	enum IV_Requirement {UNIQUE_IV = 0, RANDOM_IV, UNPREDICTABLE_RANDOM_IV, INTERNALLY_GENERATED_IV, NOT_RESYNCHRONIZABLE};
+	//! returns the minimal requirement for secure IVs
+	virtual IV_Requirement IVRequirement() const =0;
+
+	//! returns whether this object can be resynchronized (i.e. supports initialization vectors)
+	/*! If this function returns true, and no IV is passed to SetKey() and CanUseStructuredIVs()==true, an IV of all 0's will be assumed. */
+	bool IsResynchronizable() const {return IVRequirement() < NOT_RESYNCHRONIZABLE;}
+	//! returns whether this object can use random IVs (in addition to ones returned by GetNextIV)
+	bool CanUseRandomIVs() const {return IVRequirement() <= UNPREDICTABLE_RANDOM_IV;}
+	//! returns whether this object can use random but possibly predictable IVs (in addition to ones returned by GetNextIV)
+	bool CanUsePredictableIVs() const {return IVRequirement() <= RANDOM_IV;}
+	//! returns whether this object can use structured IVs, for example a counter (in addition to ones returned by GetNextIV)
+	bool CanUseStructuredIVs() const {return IVRequirement() <= UNIQUE_IV;}
+
+	virtual unsigned int IVSize() const {throw NotImplemented(GetAlgorithm().AlgorithmName() + ": this object doesn't support resynchronization");}
+	//! returns default length of IVs accepted by this object
+	unsigned int DefaultIVLength() const {return IVSize();}
+	//! returns minimal length of IVs accepted by this object
+	virtual unsigned int MinIVLength() const {return IVSize();}
+	//! returns maximal length of IVs accepted by this object
+	virtual unsigned int MaxIVLength() const {return IVSize();}
+	//! resynchronize with an IV. ivLength=-1 means use IVSize()
+	virtual void Resynchronize(const byte *iv, int ivLength=-1) {throw NotImplemented(GetAlgorithm().AlgorithmName() + ": this object doesn't support resynchronization");}
+	//! get a secure IV for the next message
+	/*! This method should be called after you finish encrypting one message and are ready to start the next one.
+		After calling it, you must call SetKey() or Resynchronize() before using this object again. 
+		This method is not implemented on decryption objects. */
+	virtual void GetNextIV(RandomNumberGenerator &rng, byte *IV);
+
+protected:
+	virtual const Algorithm & GetAlgorithm() const =0;
+	virtual void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params) =0;
+
+	void ThrowIfInvalidKeyLength(size_t length);
+	void ThrowIfResynchronizable();			// to be called when no IV is passed
+	void ThrowIfInvalidIV(const byte *iv);	// check for NULL IV if it can't be used
+	size_t ThrowIfInvalidIVLength(int size);
+	const byte * GetIVAndThrowIfInvalid(const NameValuePairs &params, size_t &size);
+	inline void AssertValidKeyLength(size_t length) const
+		{assert(IsValidKeyLength(length));}
+};
+
+//! interface for the data processing part of block ciphers
+
+/*! Classes derived from BlockTransformation are block ciphers
+	in ECB mode (for example the DES::Encryption class), which are stateless.
+	These classes should not be used directly, but only in combination with
+	a mode class (see CipherModeDocumentation in modes.h).
+*/
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE BlockTransformation : public Algorithm
+{
+public:
+	//! encrypt or decrypt inBlock, xor with xorBlock, and write to outBlock
+	virtual void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const =0;
+
+	//! encrypt or decrypt one block
+	/*! \pre size of inBlock and outBlock == BlockSize() */
+	void ProcessBlock(const byte *inBlock, byte *outBlock) const
+		{ProcessAndXorBlock(inBlock, NULL, outBlock);}
+
+	//! encrypt or decrypt one block in place
+	void ProcessBlock(byte *inoutBlock) const
+		{ProcessAndXorBlock(inoutBlock, NULL, inoutBlock);}
+
+	//! block size of the cipher in bytes
+	virtual unsigned int BlockSize() const =0;
+
+	//! returns how inputs and outputs should be aligned for optimal performance
+	virtual unsigned int OptimalDataAlignment() const;
+
+	//! returns true if this is a permutation (i.e. there is an inverse transformation)
+	virtual bool IsPermutation() const {return true;}
+
+	//! returns true if this is an encryption object
+	virtual bool IsForwardTransformation() const =0;
+
+	//! return number of blocks that can be processed in parallel, for bit-slicing implementations
+	virtual unsigned int OptimalNumberOfParallelBlocks() const {return 1;}
+
+	enum {BT_InBlockIsCounter=1, BT_DontIncrementInOutPointers=2, BT_XorInput=4, BT_ReverseDirection=8} FlagsForAdvancedProcessBlocks;
+
+	//! encrypt and xor blocks according to flags (see FlagsForAdvancedProcessBlocks)
+	/*! /note If BT_InBlockIsCounter is set, last byte of inBlocks may be modified. */
+	virtual size_t AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const;
+
+	inline CipherDir GetCipherDirection() const {return IsForwardTransformation() ? ENCRYPTION : DECRYPTION;}
+};
+
+//! interface for the data processing part of stream ciphers
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE StreamTransformation : public Algorithm
+{
+public:
+	//! return a reference to this object, 
+	/*! This function is useful for passing a temporary StreamTransformation object to a 
+		function that takes a non-const reference. */
+	StreamTransformation& Ref() {return *this;}
+
+	//! returns block size, if input must be processed in blocks, otherwise 1
+	virtual unsigned int MandatoryBlockSize() const {return 1;}
+
+	//! returns the input block size that is most efficient for this cipher
+	/*! \note optimal input length is n * OptimalBlockSize() - GetOptimalBlockSizeUsed() for any n > 0 */
+	virtual unsigned int OptimalBlockSize() const {return MandatoryBlockSize();}
+	//! returns how much of the current block is used up
+	virtual unsigned int GetOptimalBlockSizeUsed() const {return 0;}
+
+	//! returns how input should be aligned for optimal performance
+	virtual unsigned int OptimalDataAlignment() const;
+
+	//! encrypt or decrypt an array of bytes of specified length
+	/*! \note either inString == outString, or they don't overlap */
+	virtual void ProcessData(byte *outString, const byte *inString, size_t length) =0;
+
+	//! for ciphers where the last block of data is special, encrypt or decrypt the last block of data
+	/*! For now the only use of this function is for CBC-CTS mode. */
+	virtual void ProcessLastBlock(byte *outString, const byte *inString, size_t length);
+	//! returns the minimum size of the last block, 0 indicating the last block is not special
+	virtual unsigned int MinLastBlockSize() const {return 0;}
+
+	//! same as ProcessData(inoutString, inoutString, length)
+	inline void ProcessString(byte *inoutString, size_t length)
+		{ProcessData(inoutString, inoutString, length);}
+	//! same as ProcessData(outString, inString, length)
+	inline void ProcessString(byte *outString, const byte *inString, size_t length)
+		{ProcessData(outString, inString, length);}
+	//! implemented as {ProcessData(&input, &input, 1); return input;}
+	inline byte ProcessByte(byte input)
+		{ProcessData(&input, &input, 1); return input;}
+
+	//! returns whether this cipher supports random access
+	virtual bool IsRandomAccess() const =0;
+	//! for random access ciphers, seek to an absolute position
+	virtual void Seek(lword n)
+	{
+		assert(!IsRandomAccess());
+		throw NotImplemented("StreamTransformation: this object doesn't support random access");
+	}
+
+	//! returns whether this transformation is self-inverting (e.g. xor with a keystream)
+	virtual bool IsSelfInverting() const =0;
+	//! returns whether this is an encryption object
+	virtual bool IsForwardTransformation() const =0;
+};
+
+//! interface for hash functions and data processing part of MACs
+
+/*! HashTransformation objects are stateful.  They are created in an initial state,
+	change state as Update() is called, and return to the initial
+	state when Final() is called.  This interface allows a large message to
+	be hashed in pieces by calling Update() on each piece followed by
+	calling Final().
+*/
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE HashTransformation : public Algorithm
+{
+public:
+	//! return a reference to this object, 
+	/*! This function is useful for passing a temporary HashTransformation object to a 
+		function that takes a non-const reference. */
+	HashTransformation& Ref() {return *this;}
+
+	//! process more input
+	virtual void Update(const byte *input, size_t length) =0;
+
+	//! request space to write input into
+	virtual byte * CreateUpdateSpace(size_t &size) {size=0; return NULL;}
+
+	//! compute hash for current message, then restart for a new message
+	/*!	\pre size of digest == DigestSize(). */
+	virtual void Final(byte *digest)
+		{TruncatedFinal(digest, DigestSize());}
+
+	//! discard the current state, and restart with a new message
+	virtual void Restart()
+		{TruncatedFinal(NULL, 0);}
+
+	//! size of the hash/digest/MAC returned by Final()
+	virtual unsigned int DigestSize() const =0;
+
+	//! same as DigestSize()
+	unsigned int TagSize() const {return DigestSize();}
+
+
+	//! block size of underlying compression function, or 0 if not block based
+	virtual unsigned int BlockSize() const {return 0;}
+
+	//! input to Update() should have length a multiple of this for optimal speed
+	virtual unsigned int OptimalBlockSize() const {return 1;}
+
+	//! returns how input should be aligned for optimal performance
+	virtual unsigned int OptimalDataAlignment() const;
+
+	//! use this if your input is in one piece and you don't want to call Update() and Final() separately
+	virtual void CalculateDigest(byte *digest, const byte *input, size_t length)
+		{Update(input, length); Final(digest);}
+
+	//! verify that digest is a valid digest for the current message, then reinitialize the object
+	/*! Default implementation is to call Final() and do a bitwise comparison
+		between its output and digest. */
+	virtual bool Verify(const byte *digest)
+		{return TruncatedVerify(digest, DigestSize());}
+
+	//! use this if your input is in one piece and you don't want to call Update() and Verify() separately
+	virtual bool VerifyDigest(const byte *digest, const byte *input, size_t length)
+		{Update(input, length); return Verify(digest);}
+
+	//! truncated version of Final()
+	virtual void TruncatedFinal(byte *digest, size_t digestSize) =0;
+
+	//! truncated version of CalculateDigest()
+	virtual void CalculateTruncatedDigest(byte *digest, size_t digestSize, const byte *input, size_t length)
+		{Update(input, length); TruncatedFinal(digest, digestSize);}
+
+	//! truncated version of Verify()
+	virtual bool TruncatedVerify(const byte *digest, size_t digestLength);
+
+	//! truncated version of VerifyDigest()
+	virtual bool VerifyTruncatedDigest(const byte *digest, size_t digestLength, const byte *input, size_t length)
+		{Update(input, length); return TruncatedVerify(digest, digestLength);}
+
+protected:
+	void ThrowIfInvalidTruncatedSize(size_t size) const;
+};
+
+typedef HashTransformation HashFunction;
+
+//! interface for one direction (encryption or decryption) of a block cipher
+/*! \note These objects usually should not be used directly. See BlockTransformation for more details. */
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE BlockCipher : public SimpleKeyingInterface, public BlockTransformation
+{
+protected:
+	const Algorithm & GetAlgorithm() const {return *this;}
+};
+
+//! interface for one direction (encryption or decryption) of a stream cipher or cipher mode
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE SymmetricCipher : public SimpleKeyingInterface, public StreamTransformation
+{
+protected:
+	const Algorithm & GetAlgorithm() const {return *this;}
+};
+
+//! interface for message authentication codes
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE MessageAuthenticationCode : public SimpleKeyingInterface, public HashTransformation
+{
+protected:
+	const Algorithm & GetAlgorithm() const {return *this;}
+};
+
+//! interface for for one direction (encryption or decryption) of a stream cipher or block cipher mode with authentication
+/*! The StreamTransformation part of this interface is used to encrypt/decrypt the data, and the MessageAuthenticationCode part of this
+	interface is used to input additional authenticated data (AAD, which is MAC'ed but not encrypted), and to generate/verify the MAC. */
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AuthenticatedSymmetricCipher : public MessageAuthenticationCode, public StreamTransformation
+{
+public:
+	//! this indicates that a member function was called in the wrong state, for example trying to encrypt a message before having set the key or IV
+	class BadState : public Exception
+	{
+	public:
+		explicit BadState(const std::string &name, const char *message) : Exception(OTHER_ERROR, name + ": " + message) {}
+		explicit BadState(const std::string &name, const char *function, const char *state) : Exception(OTHER_ERROR, name + ": " + function + " was called before " + state) {}
+	};
+
+	//! the maximum length of AAD that can be input before the encrypted data
+	virtual lword MaxHeaderLength() const =0;
+	//! the maximum length of encrypted data
+	virtual lword MaxMessageLength() const =0;
+	//! the maximum length of AAD that can be input after the encrypted data
+	virtual lword MaxFooterLength() const {return 0;}
+	//! if this function returns true, SpecifyDataLengths() must be called before attempting to input data
+	/*! This is the case for some schemes, such as CCM. */
+	virtual bool NeedsPrespecifiedDataLengths() const {return false;}
+	//! this function only needs to be called if NeedsPrespecifiedDataLengths() returns true
+	void SpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength=0);
+	//! encrypt and generate MAC in one call. will truncate MAC if macSize < TagSize()
+	virtual void EncryptAndAuthenticate(byte *ciphertext, byte *mac, size_t macSize, const byte *iv, int ivLength, const byte *header, size_t headerLength, const byte *message, size_t messageLength);
+	//! decrypt and verify MAC in one call, returning true iff MAC is valid. will assume MAC is truncated if macLength < TagSize()
+	virtual bool DecryptAndVerify(byte *message, const byte *mac, size_t macLength, const byte *iv, int ivLength, const byte *header, size_t headerLength, const byte *ciphertext, size_t ciphertextLength);
+
+	// redeclare this to avoid compiler ambiguity errors
+	virtual std::string AlgorithmName() const =0;
+
+protected:
+	const Algorithm & GetAlgorithm() const {return *static_cast<const MessageAuthenticationCode *>(this);}
+	virtual void UncheckedSpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength) {}
+};
+
+#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
+typedef SymmetricCipher StreamCipher;
+#endif
+
+//! interface for random number generators
+/*! All return values are uniformly distributed over the range specified.
+*/
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE RandomNumberGenerator : public Algorithm
+{
+public:
+	//! update RNG state with additional unpredictable values
+	virtual void IncorporateEntropy(const byte *input, size_t length) {throw NotImplemented("RandomNumberGenerator: IncorporateEntropy not implemented");}
+
+	//! returns true if IncorporateEntropy is implemented
+	virtual bool CanIncorporateEntropy() const {return false;}
+
+	//! generate new random byte and return it
+	virtual byte GenerateByte();
+
+	//! generate new random bit and return it
+	/*! Default implementation is to call GenerateByte() and return its lowest bit. */
+	virtual unsigned int GenerateBit();
+
+	//! generate a random 32 bit word in the range min to max, inclusive
+	virtual word32 GenerateWord32(word32 a=0, word32 b=0xffffffffL);
+
+	//! generate random array of bytes
+	virtual void GenerateBlock(byte *output, size_t size);
+
+	//! generate and discard n bytes
+	virtual void DiscardBytes(size_t n);
+
+	//! generate random bytes as input to a BufferedTransformation
+	virtual void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword length);
+
+	//! randomly shuffle the specified array, resulting permutation is uniformly distributed
+	template <class IT> void Shuffle(IT begin, IT end)
+	{
+		for (; begin != end; ++begin)
+			std::iter_swap(begin, begin + GenerateWord32(0, end-begin-1));
+	}
+
+#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
+	byte GetByte() {return GenerateByte();}
+	unsigned int GetBit() {return GenerateBit();}
+	word32 GetLong(word32 a=0, word32 b=0xffffffffL) {return GenerateWord32(a, b);}
+	word16 GetShort(word16 a=0, word16 b=0xffff) {return (word16)GenerateWord32(a, b);}
+	void GetBlock(byte *output, size_t size) {GenerateBlock(output, size);}
+#endif
+};
+
+//! returns a reference that can be passed to functions that ask for a RNG but doesn't actually use it
+CRYPTOPP_DLL RandomNumberGenerator & CRYPTOPP_API NullRNG();
+
+class WaitObjectContainer;
+class CallStack;
+
+//! interface for objects that you can wait for
+
+class CRYPTOPP_NO_VTABLE Waitable
+{
+public:
+	virtual ~Waitable() {}
+
+	//! maximum number of wait objects that this object can return
+	virtual unsigned int GetMaxWaitObjectCount() const =0;
+	//! put wait objects into container
+	/*! \param callStack is used for tracing no wait loops, example:
+	             something.GetWaitObjects(c, CallStack("my func after X", 0));
+			   - or in an outer GetWaitObjects() method that itself takes a callStack parameter:
+			     innerThing.GetWaitObjects(c, CallStack("MyClass::GetWaitObjects at X", &callStack)); */
+	virtual void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack) =0;
+	//! wait on this object
+	/*! same as creating an empty container, calling GetWaitObjects(), and calling Wait() on the container */
+	bool Wait(unsigned long milliseconds, CallStack const& callStack);
+};
+
+//! the default channel for BufferedTransformation, equal to the empty string
+extern CRYPTOPP_DLL const std::string DEFAULT_CHANNEL;
+
+//! channel for additional authenticated data, equal to "AAD"
+extern CRYPTOPP_DLL const std::string AAD_CHANNEL;
+
+//! interface for buffered transformations
+
+/*! BufferedTransformation is a generalization of BlockTransformation,
+	StreamTransformation, and HashTransformation.
+
+	A buffered transformation is an object that takes a stream of bytes
+	as input (this may be done in stages), does some computation on them, and
+	then places the result into an internal buffer for later retrieval.  Any
+	partial result already in the output buffer is not modified by further
+	input.
+
+	If a method takes a "blocking" parameter, and you
+	pass "false" for it, the method will return before all input has been processed if
+	the input cannot be processed without waiting (for network buffers to become available, for example).
+	In this case the method will return true
+	or a non-zero integer value. When this happens you must continue to call the method with the same
+	parameters until it returns false or zero, before calling any other method on it or
+	attached BufferedTransformation. The integer return value in this case is approximately
+	the number of bytes left to be processed, and can be used to implement a progress bar.
+
+	For functions that take a "propagation" parameter, propagation != 0 means pass on the signal to attached
+	BufferedTransformation objects, with propagation decremented at each step until it reaches 0.
+	-1 means unlimited propagation.
+
+	\nosubgrouping
+*/
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE BufferedTransformation : public Algorithm, public Waitable
+{
+public:
+	// placed up here for CW8
+	static const std::string &NULL_CHANNEL;	// same as DEFAULT_CHANNEL, for backwards compatibility
+
+	BufferedTransformation() : Algorithm(false) {}
+
+	//! return a reference to this object
+	/*! This function is useful for passing a temporary BufferedTransformation object to a 
+		function that takes a non-const reference. */
+	BufferedTransformation& Ref() {return *this;}
+
+	//!	\name INPUT
+	//@{
+		//! input a byte for processing
+		size_t Put(byte inByte, bool blocking=true)
+			{return Put(&inByte, 1, blocking);}
+		//! input multiple bytes
+		size_t Put(const byte *inString, size_t length, bool blocking=true)
+			{return Put2(inString, length, 0, blocking);}
+
+		//! input a 16-bit word
+		size_t PutWord16(word16 value, ByteOrder order=BIG_ENDIAN_ORDER, bool blocking=true);
+		//! input a 32-bit word
+		size_t PutWord32(word32 value, ByteOrder order=BIG_ENDIAN_ORDER, bool blocking=true);
+
+		//! request space which can be written into by the caller, and then used as input to Put()
+		/*! \param size is requested size (as a hint) for input, and size of the returned space for output */
+		/*! \note The purpose of this method is to help avoid doing extra memory allocations. */
+		virtual byte * CreatePutSpace(size_t &size) {size=0; return NULL;}
+
+		virtual bool CanModifyInput() const {return false;}
+
+		//! input multiple bytes that may be modified by callee
+		size_t PutModifiable(byte *inString, size_t length, bool blocking=true)
+			{return PutModifiable2(inString, length, 0, blocking);}
+
+		bool MessageEnd(int propagation=-1, bool blocking=true)
+			{return !!Put2(NULL, 0, propagation < 0 ? -1 : propagation+1, blocking);}
+		size_t PutMessageEnd(const byte *inString, size_t length, int propagation=-1, bool blocking=true)
+			{return Put2(inString, length, propagation < 0 ? -1 : propagation+1, blocking);}
+
+		//! input multiple bytes for blocking or non-blocking processing
+		/*! \param messageEnd means how many filters to signal MessageEnd to, including this one */
+		virtual size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking) =0;
+		//! input multiple bytes that may be modified by callee for blocking or non-blocking processing
+		/*! \param messageEnd means how many filters to signal MessageEnd to, including this one */
+		virtual size_t PutModifiable2(byte *inString, size_t length, int messageEnd, bool blocking)
+			{return Put2(inString, length, messageEnd, blocking);}
+
+		//! thrown by objects that have not implemented nonblocking input processing
+		struct BlockingInputOnly : public NotImplemented
+			{BlockingInputOnly(const std::string &s) : NotImplemented(s + ": Nonblocking input is not implemented by this object.") {}};
+	//@}
+
+	//!	\name WAITING
+	//@{
+		unsigned int GetMaxWaitObjectCount() const;
+		void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack);
+	//@}
+
+	//!	\name SIGNALS
+	//@{
+		virtual void IsolatedInitialize(const NameValuePairs &parameters) {throw NotImplemented("BufferedTransformation: this object can't be reinitialized");}
+		virtual bool IsolatedFlush(bool hardFlush, bool blocking) =0;
+		virtual bool IsolatedMessageSeriesEnd(bool blocking) {return false;}
+
+		//! initialize or reinitialize this object
+		virtual void Initialize(const NameValuePairs &parameters=g_nullNameValuePairs, int propagation=-1);
+		//! flush buffered input and/or output
+		/*! \param hardFlush is used to indicate whether all data should be flushed
+			\note Hard flushes must be used with care. It means try to process and output everything, even if
+			there may not be enough data to complete the action. For example, hard flushing a HexDecoder would
+			cause an error if you do it after inputing an odd number of hex encoded characters.
+			For some types of filters, for example ZlibDecompressor, hard flushes can only
+			be done at "synchronization points". These synchronization points are positions in the data
+			stream that are created by hard flushes on the corresponding reverse filters, in this
+			example ZlibCompressor. This is useful when zlib compressed data is moved across a
+			network in packets and compression state is preserved across packets, as in the ssh2 protocol.
+		*/
+		virtual bool Flush(bool hardFlush, int propagation=-1, bool blocking=true);
+		//! mark end of a series of messages
+		/*! There should be a MessageEnd immediately before MessageSeriesEnd. */
+		virtual bool MessageSeriesEnd(int propagation=-1, bool blocking=true);
+
+		//! set propagation of automatically generated and transferred signals
+		/*! propagation == 0 means do not automaticly generate signals */
+		virtual void SetAutoSignalPropagation(int propagation) {}
+
+		//!
+		virtual int GetAutoSignalPropagation() const {return 0;}
+public:
+
+#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
+		void Close() {MessageEnd();}
+#endif
+	//@}
+
+	//!	\name RETRIEVAL OF ONE MESSAGE
+	//@{
+		//! returns number of bytes that is currently ready for retrieval
+		/*! All retrieval functions return the actual number of bytes
+			retrieved, which is the lesser of the request number and
+			MaxRetrievable(). */
+		virtual lword MaxRetrievable() const;
+
+		//! returns whether any bytes are currently ready for retrieval
+		virtual bool AnyRetrievable() const;
+
+		//! try to retrieve a single byte
+		virtual size_t Get(byte &outByte);
+		//! try to retrieve multiple bytes
+		virtual size_t Get(byte *outString, size_t getMax);
+
+		//! peek at the next byte without removing it from the output buffer
+		virtual size_t Peek(byte &outByte) const;
+		//! peek at multiple bytes without removing them from the output buffer
+		virtual size_t Peek(byte *outString, size_t peekMax) const;
+
+		//! try to retrieve a 16-bit word
+		size_t GetWord16(word16 &value, ByteOrder order=BIG_ENDIAN_ORDER);
+		//! try to retrieve a 32-bit word
+		size_t GetWord32(word32 &value, ByteOrder order=BIG_ENDIAN_ORDER);
+
+		//! try to peek at a 16-bit word
+		size_t PeekWord16(word16 &value, ByteOrder order=BIG_ENDIAN_ORDER) const;
+		//! try to peek at a 32-bit word
+		size_t PeekWord32(word32 &value, ByteOrder order=BIG_ENDIAN_ORDER) const;
+
+		//! move transferMax bytes of the buffered output to target as input
+		lword TransferTo(BufferedTransformation &target, lword transferMax=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL)
+			{TransferTo2(target, transferMax, channel); return transferMax;}
+
+		//! discard skipMax bytes from the output buffer
+		virtual lword Skip(lword skipMax=LWORD_MAX);
+
+		//! copy copyMax bytes of the buffered output to target as input
+		lword CopyTo(BufferedTransformation &target, lword copyMax=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL) const
+			{return CopyRangeTo(target, 0, copyMax, channel);}
+
+		//! copy copyMax bytes of the buffered output, starting at position (relative to current position), to target as input
+		lword CopyRangeTo(BufferedTransformation &target, lword position, lword copyMax=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL) const
+			{lword i = position; CopyRangeTo2(target, i, i+copyMax, channel); return i-position;}
+
+#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
+		unsigned long MaxRetrieveable() const {return MaxRetrievable();}
+#endif
+	//@}
+
+	//!	\name RETRIEVAL OF MULTIPLE MESSAGES
+	//@{
+		//!
+		virtual lword TotalBytesRetrievable() const;
+		//! number of times MessageEnd() has been received minus messages retrieved or skipped
+		virtual unsigned int NumberOfMessages() const;
+		//! returns true if NumberOfMessages() > 0
+		virtual bool AnyMessages() const;
+		//! start retrieving the next message
+		/*!
+			Returns false if no more messages exist or this message 
+			is not completely retrieved.
+		*/
+		virtual bool GetNextMessage();
+		//! skip count number of messages
+		virtual unsigned int SkipMessages(unsigned int count=UINT_MAX);
+		//!
+		unsigned int TransferMessagesTo(BufferedTransformation &target, unsigned int count=UINT_MAX, const std::string &channel=DEFAULT_CHANNEL)
+			{TransferMessagesTo2(target, count, channel); return count;}
+		//!
+		unsigned int CopyMessagesTo(BufferedTransformation &target, unsigned int count=UINT_MAX, const std::string &channel=DEFAULT_CHANNEL) const;
+
+		//!
+		virtual void SkipAll();
+		//!
+		void TransferAllTo(BufferedTransformation &target, const std::string &channel=DEFAULT_CHANNEL)
+			{TransferAllTo2(target, channel);}
+		//!
+		void CopyAllTo(BufferedTransformation &target, const std::string &channel=DEFAULT_CHANNEL) const;
+
+		virtual bool GetNextMessageSeries() {return false;}
+		virtual unsigned int NumberOfMessagesInThisSeries() const {return NumberOfMessages();}
+		virtual unsigned int NumberOfMessageSeries() const {return 0;}
+	//@}
+
+	//!	\name NON-BLOCKING TRANSFER OF OUTPUT
+	//@{
+		//! upon return, byteCount contains number of bytes that have finished being transfered, and returns the number of bytes left in the current transfer block
+		virtual size_t TransferTo2(BufferedTransformation &target, lword &byteCount, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) =0;
+		//! upon return, begin contains the start position of data yet to be finished copying, and returns the number of bytes left in the current transfer block
+		virtual size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const =0;
+		//! upon return, messageCount contains number of messages that have finished being transfered, and returns the number of bytes left in the current transfer block
+		size_t TransferMessagesTo2(BufferedTransformation &target, unsigned int &messageCount, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
+		//! returns the number of bytes left in the current transfer block
+		size_t TransferAllTo2(BufferedTransformation &target, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
+	//@}
+
+	//!	\name CHANNELS
+	//@{
+		struct NoChannelSupport : public NotImplemented
+			{NoChannelSupport(const std::string &name) : NotImplemented(name + ": this object doesn't support multiple channels") {}};
+		struct InvalidChannelName : public InvalidArgument
+			{InvalidChannelName(const std::string &name, const std::string &channel) : InvalidArgument(name + ": unexpected channel name \"" + channel + "\"") {}};
+
+		size_t ChannelPut(const std::string &channel, byte inByte, bool blocking=true)
+			{return ChannelPut(channel, &inByte, 1, blocking);}
+		size_t ChannelPut(const std::string &channel, const byte *inString, size_t length, bool blocking=true)
+			{return ChannelPut2(channel, inString, length, 0, blocking);}
+
+		size_t ChannelPutModifiable(const std::string &channel, byte *inString, size_t length, bool blocking=true)
+			{return ChannelPutModifiable2(channel, inString, length, 0, blocking);}
+
+		size_t ChannelPutWord16(const std::string &channel, word16 value, ByteOrder order=BIG_ENDIAN_ORDER, bool blocking=true);
+		size_t ChannelPutWord32(const std::string &channel, word32 value, ByteOrder order=BIG_ENDIAN_ORDER, bool blocking=true);
+
+		bool ChannelMessageEnd(const std::string &channel, int propagation=-1, bool blocking=true)
+			{return !!ChannelPut2(channel, NULL, 0, propagation < 0 ? -1 : propagation+1, blocking);}
+		size_t ChannelPutMessageEnd(const std::string &channel, const byte *inString, size_t length, int propagation=-1, bool blocking=true)
+			{return ChannelPut2(channel, inString, length, propagation < 0 ? -1 : propagation+1, blocking);}
+
+		virtual byte * ChannelCreatePutSpace(const std::string &channel, size_t &size);
+
+		virtual size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking);
+		virtual size_t ChannelPutModifiable2(const std::string &channel, byte *begin, size_t length, int messageEnd, bool blocking);
+
+		virtual bool ChannelFlush(const std::string &channel, bool hardFlush, int propagation=-1, bool blocking=true);
+		virtual bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true);
+
+		virtual void SetRetrievalChannel(const std::string &channel);
+	//@}
+
+	//!	\name ATTACHMENT
+	/*! Some BufferedTransformation objects (e.g. Filter objects)
+		allow other BufferedTransformation objects to be attached. When
+		this is done, the first object instead of buffering its output,
+		sents that output to the attached object as input. The entire
+		attachment chain is deleted when the anchor object is destructed.
+	*/
+	//@{
+		//! returns whether this object allows attachment
+		virtual bool Attachable() {return false;}
+		//! returns the object immediately attached to this object or NULL for no attachment
+		virtual BufferedTransformation *AttachedTransformation() {assert(!Attachable()); return 0;}
+		//!
+		virtual const BufferedTransformation *AttachedTransformation() const
+			{return const_cast<BufferedTransformation *>(this)->AttachedTransformation();}
+		//! delete the current attachment chain and replace it with newAttachment
+		virtual void Detach(BufferedTransformation *newAttachment = 0)
+			{assert(!Attachable()); throw NotImplemented("BufferedTransformation: this object is not attachable");}
+		//! add newAttachment to the end of attachment chain
+		virtual void Attach(BufferedTransformation *newAttachment);
+	//@}
+
+protected:
+	static int DecrementPropagation(int propagation)
+		{return propagation != 0 ? propagation - 1 : 0;}
+
+private:
+	byte m_buf[4];	// for ChannelPutWord16 and ChannelPutWord32, to ensure buffer isn't deallocated before non-blocking operation completes
+};
+
+//! returns a reference to a BufferedTransformation object that discards all input
+BufferedTransformation & TheBitBucket();
+
+//! interface for crypto material, such as public and private keys, and crypto parameters
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CryptoMaterial : public NameValuePairs
+{
+public:
+	//! exception thrown when invalid crypto material is detected
+	class CRYPTOPP_DLL InvalidMaterial : public InvalidDataFormat
+	{
+	public:
+		explicit InvalidMaterial(const std::string &s) : InvalidDataFormat(s) {}
+	};
+
+	//! assign values from source to this object
+	/*! \note This function can be used to create a public key from a private key. */
+	virtual void AssignFrom(const NameValuePairs &source) =0;
+
+	//! check this object for errors
+	/*! \param level denotes the level of thoroughness:
+		0 - using this object won't cause a crash or exception (rng is ignored)
+		1 - this object will probably function (encrypt, sign, etc.) correctly (but may not check for weak keys and such)
+		2 - make sure this object will function correctly, and do reasonable security checks
+		3 - do checks that may take a long time
+		\return true if the tests pass */
+	virtual bool Validate(RandomNumberGenerator &rng, unsigned int level) const =0;
+
+	//! throws InvalidMaterial if this object fails Validate() test
+	virtual void ThrowIfInvalid(RandomNumberGenerator &rng, unsigned int level) const
+		{if (!Validate(rng, level)) throw InvalidMaterial("CryptoMaterial: this object contains invalid values");}
+
+//	virtual std::vector<std::string> GetSupportedFormats(bool includeSaveOnly=false, bool includeLoadOnly=false);
+
+	//! save key into a BufferedTransformation
+	virtual void Save(BufferedTransformation &bt) const
+		{throw NotImplemented("CryptoMaterial: this object does not support saving");}
+
+	//! load key from a BufferedTransformation
+	/*! \throws KeyingErr if decode fails
+		\note Generally does not check that the key is valid.
+			Call ValidateKey() or ThrowIfInvalidKey() to check that. */
+	virtual void Load(BufferedTransformation &bt)
+		{throw NotImplemented("CryptoMaterial: this object does not support loading");}
+
+	//! \return whether this object supports precomputation
+	virtual bool SupportsPrecomputation() const {return false;}
+	//! do precomputation
+	/*! The exact semantics of Precompute() is varies, but
+		typically it means calculate a table of n objects
+		that can be used later to speed up computation. */
+	virtual void Precompute(unsigned int n)
+		{assert(!SupportsPrecomputation()); throw NotImplemented("CryptoMaterial: this object does not support precomputation");}
+	//! retrieve previously saved precomputation
+	virtual void LoadPrecomputation(BufferedTransformation &storedPrecomputation)
+		{assert(!SupportsPrecomputation()); throw NotImplemented("CryptoMaterial: this object does not support precomputation");}
+	//! save precomputation for later use
+	virtual void SavePrecomputation(BufferedTransformation &storedPrecomputation) const
+		{assert(!SupportsPrecomputation()); throw NotImplemented("CryptoMaterial: this object does not support precomputation");}
+
+	// for internal library use
+	void DoQuickSanityCheck() const	{ThrowIfInvalid(NullRNG(), 0);}
+
+#if (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590)
+	// Sun Studio 11/CC 5.8 workaround: it generates incorrect code when casting to an empty virtual base class
+	char m_sunCCworkaround;
+#endif
+};
+
+//! interface for generatable crypto material, such as private keys and crypto parameters
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE GeneratableCryptoMaterial : virtual public CryptoMaterial
+{
+public:
+	//! generate a random key or crypto parameters
+	/*! \throws KeyingErr if algorithm parameters are invalid, or if a key can't be generated
+		(e.g., if this is a public key object) */
+	virtual void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &params = g_nullNameValuePairs)
+		{throw NotImplemented("GeneratableCryptoMaterial: this object does not support key/parameter generation");}
+
+	//! calls the above function with a NameValuePairs object that just specifies "KeySize"
+	void GenerateRandomWithKeySize(RandomNumberGenerator &rng, unsigned int keySize);
+};
+
+//! interface for public keys
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PublicKey : virtual public CryptoMaterial
+{
+};
+
+//! interface for private keys
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PrivateKey : public GeneratableCryptoMaterial
+{
+};
+
+//! interface for crypto prameters
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CryptoParameters : public GeneratableCryptoMaterial
+{
+};
+
+//! interface for asymmetric algorithms
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AsymmetricAlgorithm : public Algorithm
+{
+public:
+	//! returns a reference to the crypto material used by this object
+	virtual CryptoMaterial & AccessMaterial() =0;
+	//! returns a const reference to the crypto material used by this object
+	virtual const CryptoMaterial & GetMaterial() const =0;
+
+	//! for backwards compatibility, calls AccessMaterial().Load(bt)
+	void BERDecode(BufferedTransformation &bt)
+		{AccessMaterial().Load(bt);}
+	//! for backwards compatibility, calls GetMaterial().Save(bt)
+	void DEREncode(BufferedTransformation &bt) const
+		{GetMaterial().Save(bt);}
+};
+
+//! interface for asymmetric algorithms using public keys
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PublicKeyAlgorithm : public AsymmetricAlgorithm
+{
+public:
+	// VC60 workaround: no co-variant return type
+	CryptoMaterial & AccessMaterial() {return AccessPublicKey();}
+	const CryptoMaterial & GetMaterial() const {return GetPublicKey();}
+
+	virtual PublicKey & AccessPublicKey() =0;
+	virtual const PublicKey & GetPublicKey() const {return const_cast<PublicKeyAlgorithm *>(this)->AccessPublicKey();}
+};
+
+//! interface for asymmetric algorithms using private keys
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PrivateKeyAlgorithm : public AsymmetricAlgorithm
+{
+public:
+	CryptoMaterial & AccessMaterial() {return AccessPrivateKey();}
+	const CryptoMaterial & GetMaterial() const {return GetPrivateKey();}
+
+	virtual PrivateKey & AccessPrivateKey() =0;
+	virtual const PrivateKey & GetPrivateKey() const {return const_cast<PrivateKeyAlgorithm *>(this)->AccessPrivateKey();}
+};
+
+//! interface for key agreement algorithms
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE KeyAgreementAlgorithm : public AsymmetricAlgorithm
+{
+public:
+	CryptoMaterial & AccessMaterial() {return AccessCryptoParameters();}
+	const CryptoMaterial & GetMaterial() const {return GetCryptoParameters();}
+
+	virtual CryptoParameters & AccessCryptoParameters() =0;
+	virtual const CryptoParameters & GetCryptoParameters() const {return const_cast<KeyAgreementAlgorithm *>(this)->AccessCryptoParameters();}
+};
+
+//! interface for public-key encryptors and decryptors
+
+/*! This class provides an interface common to encryptors and decryptors
+	for querying their plaintext and ciphertext lengths.
+*/
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_CryptoSystem
+{
+public:
+	virtual ~PK_CryptoSystem() {}
+
+	//! maximum length of plaintext for a given ciphertext length
+	/*! \note This function returns 0 if ciphertextLength is not valid (too long or too short). */
+	virtual size_t MaxPlaintextLength(size_t ciphertextLength) const =0;
+
+	//! calculate length of ciphertext given length of plaintext
+	/*! \note This function returns 0 if plaintextLength is not valid (too long). */
+	virtual size_t CiphertextLength(size_t plaintextLength) const =0;
+
+	//! this object supports the use of the parameter with the given name
+	/*! some possible parameter names: EncodingParameters, KeyDerivationParameters */
+	virtual bool ParameterSupported(const char *name) const =0;
+
+	//! return fixed ciphertext length, if one exists, otherwise return 0
+	/*! \note "Fixed" here means length of ciphertext does not depend on length of plaintext.
+		It usually does depend on the key length. */
+	virtual size_t FixedCiphertextLength() const {return 0;}
+
+	//! return maximum plaintext length given the fixed ciphertext length, if one exists, otherwise return 0
+	virtual size_t FixedMaxPlaintextLength() const {return 0;}
+
+#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
+	size_t MaxPlainTextLength(size_t cipherTextLength) const {return MaxPlaintextLength(cipherTextLength);}
+	size_t CipherTextLength(size_t plainTextLength) const {return CiphertextLength(plainTextLength);}
+#endif
+};
+
+//! interface for public-key encryptors
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_Encryptor : public PK_CryptoSystem, public PublicKeyAlgorithm
+{
+public:
+	//! exception thrown when trying to encrypt plaintext of invalid length
+	class CRYPTOPP_DLL InvalidPlaintextLength : public Exception
+	{
+	public:
+		InvalidPlaintextLength() : Exception(OTHER_ERROR, "PK_Encryptor: invalid plaintext length") {}
+	};
+
+	//! encrypt a byte string
+	/*! \pre CiphertextLength(plaintextLength) != 0 (i.e., plaintext isn't too long)
+		\pre size of ciphertext == CiphertextLength(plaintextLength)
+	*/
+	virtual void Encrypt(RandomNumberGenerator &rng, 
+		const byte *plaintext, size_t plaintextLength, 
+		byte *ciphertext, const NameValuePairs &parameters = g_nullNameValuePairs) const =0;
+
+	//! create a new encryption filter
+	/*! \note The caller is responsible for deleting the returned pointer.
+		\note Encoding parameters should be passed in the "EP" channel.
+	*/
+	virtual BufferedTransformation * CreateEncryptionFilter(RandomNumberGenerator &rng, 
+		BufferedTransformation *attachment=NULL, const NameValuePairs &parameters = g_nullNameValuePairs) const;
+};
+
+//! interface for public-key decryptors
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_Decryptor : public PK_CryptoSystem, public PrivateKeyAlgorithm
+{
+public:
+	//! decrypt a byte string, and return the length of plaintext
+	/*! \pre size of plaintext == MaxPlaintextLength(ciphertextLength) bytes.
+		\return the actual length of the plaintext, indication that decryption failed.
+	*/
+	virtual DecodingResult Decrypt(RandomNumberGenerator &rng, 
+		const byte *ciphertext, size_t ciphertextLength, 
+		byte *plaintext, const NameValuePairs &parameters = g_nullNameValuePairs) const =0;
+
+	//! create a new decryption filter
+	/*! \note caller is responsible for deleting the returned pointer
+	*/
+	virtual BufferedTransformation * CreateDecryptionFilter(RandomNumberGenerator &rng, 
+		BufferedTransformation *attachment=NULL, const NameValuePairs &parameters = g_nullNameValuePairs) const;
+
+	//! decrypt a fixed size ciphertext
+	DecodingResult FixedLengthDecrypt(RandomNumberGenerator &rng, const byte *ciphertext, byte *plaintext, const NameValuePairs &parameters = g_nullNameValuePairs) const
+		{return Decrypt(rng, ciphertext, FixedCiphertextLength(), plaintext, parameters);}
+};
+
+#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
+typedef PK_CryptoSystem PK_FixedLengthCryptoSystem;
+typedef PK_Encryptor PK_FixedLengthEncryptor;
+typedef PK_Decryptor PK_FixedLengthDecryptor;
+#endif
+
+//! interface for public-key signers and verifiers
+
+/*! This class provides an interface common to signers and verifiers
+	for querying scheme properties.
+*/
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_SignatureScheme
+{
+public:
+	//! invalid key exception, may be thrown by any function in this class if the private or public key has a length that can't be used
+	class CRYPTOPP_DLL InvalidKeyLength : public Exception
+	{
+	public:
+		InvalidKeyLength(const std::string &message) : Exception(OTHER_ERROR, message) {}
+	};
+
+	//! key too short exception, may be thrown by any function in this class if the private or public key is too short to sign or verify anything
+	class CRYPTOPP_DLL KeyTooShort : public InvalidKeyLength
+	{
+	public:
+		KeyTooShort() : InvalidKeyLength("PK_Signer: key too short for this signature scheme") {}
+	};
+
+	virtual ~PK_SignatureScheme() {}
+
+	//! signature length if it only depends on the key, otherwise 0
+	virtual size_t SignatureLength() const =0;
+
+	//! maximum signature length produced for a given length of recoverable message part
+	virtual size_t MaxSignatureLength(size_t recoverablePartLength = 0) const {return SignatureLength();}
+
+	//! length of longest message that can be recovered, or 0 if this signature scheme does not support message recovery
+	virtual size_t MaxRecoverableLength() const =0;
+
+	//! length of longest message that can be recovered from a signature of given length, or 0 if this signature scheme does not support message recovery
+	virtual size_t MaxRecoverableLengthFromSignatureLength(size_t signatureLength) const =0;
+
+	//! requires a random number generator to sign
+	/*! if this returns false, NullRNG() can be passed to functions that take RandomNumberGenerator & */
+	virtual bool IsProbabilistic() const =0;
+
+	//! whether or not a non-recoverable message part can be signed
+	virtual bool AllowNonrecoverablePart() const =0;
+
+	//! if this function returns true, during verification you must input the signature before the message, otherwise you can input it at anytime */
+	virtual bool SignatureUpfront() const {return false;}
+
+	//! whether you must input the recoverable part before the non-recoverable part during signing
+	virtual bool RecoverablePartFirst() const =0;
+};
+
+//! interface for accumulating messages to be signed or verified
+/*! Only Update() should be called
+	on this class. No other functions inherited from HashTransformation should be called.
+*/
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_MessageAccumulator : public HashTransformation
+{
+public:
+	//! should not be called on PK_MessageAccumulator
+	unsigned int DigestSize() const
+		{throw NotImplemented("PK_MessageAccumulator: DigestSize() should not be called");}
+	//! should not be called on PK_MessageAccumulator
+	void TruncatedFinal(byte *digest, size_t digestSize) 
+		{throw NotImplemented("PK_MessageAccumulator: TruncatedFinal() should not be called");}
+};
+
+//! interface for public-key signers
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_Signer : public PK_SignatureScheme, public PrivateKeyAlgorithm
+{
+public:
+	//! create a new HashTransformation to accumulate the message to be signed
+	virtual PK_MessageAccumulator * NewSignatureAccumulator(RandomNumberGenerator &rng) const =0;
+
+	virtual void InputRecoverableMessage(PK_MessageAccumulator &messageAccumulator, const byte *recoverableMessage, size_t recoverableMessageLength) const =0;
+
+	//! sign and delete messageAccumulator (even in case of exception thrown)
+	/*! \pre size of signature == MaxSignatureLength()
+		\return actual signature length
+	*/
+	virtual size_t Sign(RandomNumberGenerator &rng, PK_MessageAccumulator *messageAccumulator, byte *signature) const;
+
+	//! sign and restart messageAccumulator
+	/*! \pre size of signature == MaxSignatureLength()
+		\return actual signature length
+	*/
+	virtual size_t SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart=true) const =0;
+
+	//! sign a message
+	/*! \pre size of signature == MaxSignatureLength()
+		\return actual signature length
+	*/
+	virtual size_t SignMessage(RandomNumberGenerator &rng, const byte *message, size_t messageLen, byte *signature) const;
+
+	//! sign a recoverable message
+	/*! \pre size of signature == MaxSignatureLength(recoverableMessageLength)
+		\return actual signature length
+	*/
+	virtual size_t SignMessageWithRecovery(RandomNumberGenerator &rng, const byte *recoverableMessage, size_t recoverableMessageLength, 
+		const byte *nonrecoverableMessage, size_t nonrecoverableMessageLength, byte *signature) const;
+};
+
+//! interface for public-key signature verifiers
+/*! The Recover* functions throw NotImplemented if the signature scheme does not support
+	message recovery.
+	The Verify* functions throw InvalidDataFormat if the scheme does support message
+	recovery and the signature contains a non-empty recoverable message part. The
+	Recovery* functions should be used in that case.
+*/
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_Verifier : public PK_SignatureScheme, public PublicKeyAlgorithm
+{
+public:
+	//! create a new HashTransformation to accumulate the message to be verified
+	virtual PK_MessageAccumulator * NewVerificationAccumulator() const =0;
+
+	//! input signature into a message accumulator
+	virtual void InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, size_t signatureLength) const =0;
+
+	//! check whether messageAccumulator contains a valid signature and message, and delete messageAccumulator (even in case of exception thrown)
+	virtual bool Verify(PK_MessageAccumulator *messageAccumulator) const;
+
+	//! check whether messageAccumulator contains a valid signature and message, and restart messageAccumulator
+	virtual bool VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const =0;
+
+	//! check whether input signature is a valid signature for input message
+	virtual bool VerifyMessage(const byte *message, size_t messageLen, 
+		const byte *signature, size_t signatureLength) const;
+
+	//! recover a message from its signature
+	/*! \pre size of recoveredMessage == MaxRecoverableLengthFromSignatureLength(signatureLength)
+	*/
+	virtual DecodingResult Recover(byte *recoveredMessage, PK_MessageAccumulator *messageAccumulator) const;
+
+	//! recover a message from its signature
+	/*! \pre size of recoveredMessage == MaxRecoverableLengthFromSignatureLength(signatureLength)
+	*/
+	virtual DecodingResult RecoverAndRestart(byte *recoveredMessage, PK_MessageAccumulator &messageAccumulator) const =0;
+
+	//! recover a message from its signature
+	/*! \pre size of recoveredMessage == MaxRecoverableLengthFromSignatureLength(signatureLength)
+	*/
+	virtual DecodingResult RecoverMessage(byte *recoveredMessage, 
+		const byte *nonrecoverableMessage, size_t nonrecoverableMessageLength, 
+		const byte *signature, size_t signatureLength) const;
+};
+
+//! interface for domains of simple key agreement protocols
+
+/*! A key agreement domain is a set of parameters that must be shared
+	by two parties in a key agreement protocol, along with the algorithms
+	for generating key pairs and deriving agreed values.
+*/
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE SimpleKeyAgreementDomain : public KeyAgreementAlgorithm
+{
+public:
+	//! return length of agreed value produced
+	virtual unsigned int AgreedValueLength() const =0;
+	//! return length of private keys in this domain
+	virtual unsigned int PrivateKeyLength() const =0;
+	//! return length of public keys in this domain
+	virtual unsigned int PublicKeyLength() const =0;
+	//! generate private key
+	/*! \pre size of privateKey == PrivateKeyLength() */
+	virtual void GeneratePrivateKey(RandomNumberGenerator &rng, byte *privateKey) const =0;
+	//! generate public key
+	/*!	\pre size of publicKey == PublicKeyLength() */
+	virtual void GeneratePublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const =0;
+	//! generate private/public key pair
+	/*! \note equivalent to calling GeneratePrivateKey() and then GeneratePublicKey() */
+	virtual void GenerateKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const;
+	//! derive agreed value from your private key and couterparty's public key, return false in case of failure
+	/*! \note If you have previously validated the public key, use validateOtherPublicKey=false to save time.
+		\pre size of agreedValue == AgreedValueLength()
+		\pre length of privateKey == PrivateKeyLength()
+		\pre length of otherPublicKey == PublicKeyLength()
+	*/
+	virtual bool Agree(byte *agreedValue, const byte *privateKey, const byte *otherPublicKey, bool validateOtherPublicKey=true) const =0;
+
+#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
+	bool ValidateDomainParameters(RandomNumberGenerator &rng) const
+		{return GetCryptoParameters().Validate(rng, 2);}
+#endif
+};
+
+//! interface for domains of authenticated key agreement protocols
+
+/*! In an authenticated key agreement protocol, each party has two
+	key pairs. The long-lived key pair is called the static key pair,
+	and the short-lived key pair is called the ephemeral key pair.
+*/
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AuthenticatedKeyAgreementDomain : public KeyAgreementAlgorithm
+{
+public:
+	//! return length of agreed value produced
+	virtual unsigned int AgreedValueLength() const =0;
+
+	//! return length of static private keys in this domain
+	virtual unsigned int StaticPrivateKeyLength() const =0;
+	//! return length of static public keys in this domain
+	virtual unsigned int StaticPublicKeyLength() const =0;
+	//! generate static private key
+	/*! \pre size of privateKey == PrivateStaticKeyLength() */
+	virtual void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const =0;
+	//! generate static public key
+	/*!	\pre size of publicKey == PublicStaticKeyLength() */
+	virtual void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const =0;
+	//! generate private/public key pair
+	/*! \note equivalent to calling GenerateStaticPrivateKey() and then GenerateStaticPublicKey() */
+	virtual void GenerateStaticKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const;
+
+	//! return length of ephemeral private keys in this domain
+	virtual unsigned int EphemeralPrivateKeyLength() const =0;
+	//! return length of ephemeral public keys in this domain
+	virtual unsigned int EphemeralPublicKeyLength() const =0;
+	//! generate ephemeral private key
+	/*! \pre size of privateKey == PrivateEphemeralKeyLength() */
+	virtual void GenerateEphemeralPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const =0;
+	//! generate ephemeral public key
+	/*!	\pre size of publicKey == PublicEphemeralKeyLength() */
+	virtual void GenerateEphemeralPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const =0;
+	//! generate private/public key pair
+	/*! \note equivalent to calling GenerateEphemeralPrivateKey() and then GenerateEphemeralPublicKey() */
+	virtual void GenerateEphemeralKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const;
+
+	//! derive agreed value from your private keys and couterparty's public keys, return false in case of failure
+	/*! \note The ephemeral public key will always be validated.
+		      If you have previously validated the static public key, use validateStaticOtherPublicKey=false to save time.
+		\pre size of agreedValue == AgreedValueLength()
+		\pre length of staticPrivateKey == StaticPrivateKeyLength()
+		\pre length of ephemeralPrivateKey == EphemeralPrivateKeyLength()
+		\pre length of staticOtherPublicKey == StaticPublicKeyLength()
+		\pre length of ephemeralOtherPublicKey == EphemeralPublicKeyLength()
+	*/
+	virtual bool Agree(byte *agreedValue,
+		const byte *staticPrivateKey, const byte *ephemeralPrivateKey,
+		const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey,
+		bool validateStaticOtherPublicKey=true) const =0;
+
+#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
+	bool ValidateDomainParameters(RandomNumberGenerator &rng) const
+		{return GetCryptoParameters().Validate(rng, 2);}
+#endif
+};
+
+// interface for password authenticated key agreement protocols, not implemented yet
+#if 0
+//! interface for protocol sessions
+/*! The methods should be called in the following order:
+
+	InitializeSession(rng, parameters);	// or call initialize method in derived class
+	while (true)
+	{
+		if (OutgoingMessageAvailable())
+		{
+			length = GetOutgoingMessageLength();
+			GetOutgoingMessage(message);
+			; // send outgoing message
+		}
+
+		if (LastMessageProcessed())
+			break;
+
+		; // receive incoming message
+		ProcessIncomingMessage(message);
+	}
+	; // call methods in derived class to obtain result of protocol session
+*/
+class ProtocolSession
+{
+public:
+	//! exception thrown when an invalid protocol message is processed
+	class ProtocolError : public Exception
+	{
+	public:
+		ProtocolError(ErrorType errorType, const std::string &s) : Exception(errorType, s) {}
+	};
+
+	//! exception thrown when a function is called unexpectedly
+	/*! for example calling ProcessIncomingMessage() when ProcessedLastMessage() == true */
+	class UnexpectedMethodCall : public Exception
+	{
+	public:
+		UnexpectedMethodCall(const std::string &s) : Exception(OTHER_ERROR, s) {}
+	};
+
+	ProtocolSession() : m_rng(NULL), m_throwOnProtocolError(true), m_validState(false) {}
+	virtual ~ProtocolSession() {}
+
+	virtual void InitializeSession(RandomNumberGenerator &rng, const NameValuePairs &parameters) =0;
+
+	bool GetThrowOnProtocolError() const {return m_throwOnProtocolError;}
+	void SetThrowOnProtocolError(bool throwOnProtocolError) {m_throwOnProtocolError = throwOnProtocolError;}
+
+	bool HasValidState() const {return m_validState;}
+
+	virtual bool OutgoingMessageAvailable() const =0;
+	virtual unsigned int GetOutgoingMessageLength() const =0;
+	virtual void GetOutgoingMessage(byte *message) =0;
+
+	virtual bool LastMessageProcessed() const =0;
+	virtual void ProcessIncomingMessage(const byte *message, unsigned int messageLength) =0;
+
+protected:
+	void HandleProtocolError(Exception::ErrorType errorType, const std::string &s) const;
+	void CheckAndHandleInvalidState() const;
+	void SetValidState(bool valid) {m_validState = valid;}
+
+	RandomNumberGenerator *m_rng;
+
+private:
+	bool m_throwOnProtocolError, m_validState;
+};
+
+class KeyAgreementSession : public ProtocolSession
+{
+public:
+	virtual unsigned int GetAgreedValueLength() const =0;
+	virtual void GetAgreedValue(byte *agreedValue) const =0;
+};
+
+class PasswordAuthenticatedKeyAgreementSession : public KeyAgreementSession
+{
+public:
+	void InitializePasswordAuthenticatedKeyAgreementSession(RandomNumberGenerator &rng, 
+		const byte *myId, unsigned int myIdLength, 
+		const byte *counterPartyId, unsigned int counterPartyIdLength, 
+		const byte *passwordOrVerifier, unsigned int passwordOrVerifierLength);
+};
+
+class PasswordAuthenticatedKeyAgreementDomain : public KeyAgreementAlgorithm
+{
+public:
+	//! return whether the domain parameters stored in this object are valid
+	virtual bool ValidateDomainParameters(RandomNumberGenerator &rng) const
+		{return GetCryptoParameters().Validate(rng, 2);}
+
+	virtual unsigned int GetPasswordVerifierLength(const byte *password, unsigned int passwordLength) const =0;
+	virtual void GeneratePasswordVerifier(RandomNumberGenerator &rng, const byte *userId, unsigned int userIdLength, const byte *password, unsigned int passwordLength, byte *verifier) const =0;
+
+	enum RoleFlags {CLIENT=1, SERVER=2, INITIATOR=4, RESPONDER=8};
+
+	virtual bool IsValidRole(unsigned int role) =0;
+	virtual PasswordAuthenticatedKeyAgreementSession * CreateProtocolSession(unsigned int role) const =0;
+};
+#endif
+
+//! BER Decode Exception Class, may be thrown during an ASN1 BER decode operation
+class CRYPTOPP_DLL BERDecodeErr : public InvalidArgument
+{
+public: 
+	BERDecodeErr() : InvalidArgument("BER decode error") {}
+	BERDecodeErr(const std::string &s) : InvalidArgument(s) {}
+};
+
+//! interface for encoding and decoding ASN1 objects
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE ASN1Object
+{
+public:
+	virtual ~ASN1Object() {}
+	//! decode this object from a BufferedTransformation, using BER (Basic Encoding Rules)
+	virtual void BERDecode(BufferedTransformation &bt) =0;
+	//! encode this object into a BufferedTransformation, using DER (Distinguished Encoding Rules)
+	virtual void DEREncode(BufferedTransformation &bt) const =0;
+	//! encode this object into a BufferedTransformation, using BER
+	/*! this may be useful if DEREncode() would be too inefficient */
+	virtual void BEREncode(BufferedTransformation &bt) const {DEREncode(bt);}
+};
+
+#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
+typedef PK_SignatureScheme PK_SignatureSystem;
+typedef SimpleKeyAgreementDomain PK_SimpleKeyAgreementDomain;
+typedef AuthenticatedKeyAgreementDomain PK_AuthenticatedKeyAgreementDomain;
+#endif
+
+NAMESPACE_END
+
+#endif
new file mode 100644
--- /dev/null
+++ b/cryptopp/iterhash.h
@@ -0,0 +1,29 @@
+#ifndef CRYPTOPP_ITERHASH_H
+#define CRYPTOPP_ITERHASH_H
+
+#include "secblock.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+// *** trimmed down dependency from iterhash.h ***
+template <class T_HashWordType, class T_Endianness, unsigned int T_BlockSize, unsigned int T_StateSize, class T_Transform, unsigned int T_DigestSize = 0, bool T_StateAligned = false>
+class CRYPTOPP_NO_VTABLE IteratedHashWithStaticTransform
+{
+public:
+	CRYPTOPP_CONSTANT(DIGESTSIZE = T_DigestSize ? T_DigestSize : T_StateSize)
+	unsigned int DigestSize() const {return DIGESTSIZE;};
+    typedef T_HashWordType HashWordType;
+    CRYPTOPP_CONSTANT(BLOCKSIZE = T_BlockSize)
+
+protected:
+	IteratedHashWithStaticTransform() {this->Init();}
+	void HashEndianCorrectedBlock(const T_HashWordType *data) {T_Transform::Transform(this->m_state, data);}
+	void Init() {T_Transform::InitState(this->m_state);}
+
+	T_HashWordType* StateBuf() {return this->m_state;}
+	FixedSizeAlignedSecBlock<T_HashWordType, T_BlockSize/sizeof(T_HashWordType), T_StateAligned> m_state;
+};
+
+NAMESPACE_END
+
+#endif
new file mode 100644
--- /dev/null
+++ b/cryptopp/misc.h
@@ -0,0 +1,1134 @@
+#ifndef CRYPTOPP_MISC_H
+#define CRYPTOPP_MISC_H
+
+#include "cryptlib.h"
+#include "smartptr.h"
+#include <string.h>		// for memcpy and memmove
+
+#ifdef _MSC_VER
+	#include <stdlib.h>
+	#if _MSC_VER >= 1400
+		// VC2005 workaround: disable declarations that conflict with winnt.h
+		#define _interlockedbittestandset CRYPTOPP_DISABLED_INTRINSIC_1
+		#define _interlockedbittestandreset CRYPTOPP_DISABLED_INTRINSIC_2
+		#define _interlockedbittestandset64 CRYPTOPP_DISABLED_INTRINSIC_3
+		#define _interlockedbittestandreset64 CRYPTOPP_DISABLED_INTRINSIC_4
+		#include <intrin.h>
+		#undef _interlockedbittestandset
+		#undef _interlockedbittestandreset
+		#undef _interlockedbittestandset64
+		#undef _interlockedbittestandreset64
+		#define CRYPTOPP_FAST_ROTATE(x) 1
+	#elif _MSC_VER >= 1300
+		#define CRYPTOPP_FAST_ROTATE(x) ((x) == 32 | (x) == 64)
+	#else
+		#define CRYPTOPP_FAST_ROTATE(x) ((x) == 32)
+	#endif
+#elif (defined(__MWERKS__) && TARGET_CPU_PPC) || \
+	(defined(__GNUC__) && (defined(_ARCH_PWR2) || defined(_ARCH_PWR) || defined(_ARCH_PPC) || defined(_ARCH_PPC64) || defined(_ARCH_COM)))
+	#define CRYPTOPP_FAST_ROTATE(x) ((x) == 32)
+#elif defined(__GNUC__) && (CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X86)	// depend on GCC's peephole optimization to generate rotate instructions
+	#define CRYPTOPP_FAST_ROTATE(x) 1
+#else
+	#define CRYPTOPP_FAST_ROTATE(x) 0
+#endif
+
+#ifdef __BORLANDC__
+#include <mem.h>
+#endif
+
+#if defined(__GNUC__) && defined(__linux__)
+#define CRYPTOPP_BYTESWAP_AVAILABLE
+#include <byteswap.h>
+#endif
+
+NAMESPACE_BEGIN(CryptoPP)
+
+// ************** compile-time assertion ***************
+
+template <bool b>
+struct CompileAssert
+{
+	static char dummy[2*b-1];
+};
+
+#define CRYPTOPP_COMPILE_ASSERT(assertion) CRYPTOPP_COMPILE_ASSERT_INSTANCE(assertion, __LINE__)
+#if defined(CRYPTOPP_EXPORTS) || defined(CRYPTOPP_IMPORTS)
+#define CRYPTOPP_COMPILE_ASSERT_INSTANCE(assertion, instance)
+#else
+#define CRYPTOPP_COMPILE_ASSERT_INSTANCE(assertion, instance) static CompileAssert<(assertion)> CRYPTOPP_ASSERT_JOIN(cryptopp_assert_, instance)
+#endif
+#define CRYPTOPP_ASSERT_JOIN(X, Y) CRYPTOPP_DO_ASSERT_JOIN(X, Y)
+#define CRYPTOPP_DO_ASSERT_JOIN(X, Y) X##Y
+
+// ************** misc classes ***************
+
+class CRYPTOPP_DLL Empty
+{
+};
+
+//! _
+template <class BASE1, class BASE2>
+class CRYPTOPP_NO_VTABLE TwoBases : public BASE1, public BASE2
+{
+};
+
+//! _
+template <class BASE1, class BASE2, class BASE3>
+class CRYPTOPP_NO_VTABLE 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 &);
+};
+
+template <class T>
+struct NewObject
+{
+	T* operator()() const {return new T;}
+};
+
+/*! This function safely initializes a static object in a multithreaded environment without using locks.
+	It may leak memory when two threads try to initialize the static object at the same time
+	but this should be acceptable since each static object is only initialized once per session.
+*/
+template <class T, class F = NewObject<T>, int instance=0>
+class Singleton
+{
+public:
+	Singleton(F objectFactory = F()) : m_objectFactory(objectFactory) {}
+
+	// prevent this function from being inlined
+	CRYPTOPP_NOINLINE const T & Ref(CRYPTOPP_NOINLINE_DOTDOTDOT) const;
+
+private:
+	F m_objectFactory;
+};
+
+template <class T, class F, int instance>
+const T & Singleton<T, F, instance>::Ref(CRYPTOPP_NOINLINE_DOTDOTDOT) const
+{
+	static simple_ptr<T> s_pObject;
+	static char s_objectState = 0;
+
+retry:
+	switch (s_objectState)
+	{
+	case 0:
+		s_objectState = 1;
+		try
+		{
+			s_pObject.m_p = m_objectFactory();
+		}
+		catch(...)
+		{
+			s_objectState = 0;
+			throw;
+		}
+		s_objectState = 2;
+		break;
+	case 1:
+		goto retry;
+	default:
+		break;
+	}
+	return *s_pObject.m_p;
+}
+
+// ************** misc functions ***************
+
+#if (!__STDC_WANT_SECURE_LIB__)
+inline void memcpy_s(void *dest, size_t sizeInBytes, const void *src, size_t count)
+{
+	if (count > sizeInBytes)
+		throw InvalidArgument("memcpy_s: buffer overflow");
+	memcpy(dest, src, count);
+}
+
+inline void memmove_s(void *dest, size_t sizeInBytes, const void *src, size_t count)
+{
+	if (count > sizeInBytes)
+		throw InvalidArgument("memmove_s: buffer overflow");
+	memmove(dest, src, count);
+}
+#endif
+
+inline void * memset_z(void *ptr, int value, size_t num)
+{
+// avoid extranous warning on GCC 4.3.2 Ubuntu 8.10
+#if CRYPTOPP_GCC_VERSION >= 30001
+	if (__builtin_constant_p(num) && num==0)
+		return ptr;
+#endif
+	return memset(ptr, value, num);
+}
+
+// can't use std::min or std::max in MSVC60 or Cygwin 1.1.0
+template <class T> inline const T& STDMIN(const T& a, const T& b)
+{
+	return b < a ? b : a;
+}
+
+template <class T1, class T2> inline const T1 UnsignedMin(const T1& a, const T2& b)
+{
+	CRYPTOPP_COMPILE_ASSERT((sizeof(T1)<=sizeof(T2) && T2(-1)>0) || (sizeof(T1)>sizeof(T2) && T1(-1)>0));
+	assert(a==0 || a>0);	// GCC workaround: get rid of the warning "comparison is always true due to limited range of data type"
+	assert(b>=0);
+
+	if (sizeof(T1)<=sizeof(T2))
+		return b < (T2)a ? (T1)b : a;
+	else
+		return (T1)b < a ? (T1)b : a;
+}
+
+template <class T> inline const T& STDMAX(const T& a, const T& b)
+{
+	return a < b ? b : a;
+}
+
+#define RETURN_IF_NONZERO(x) size_t 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])
+
+#define CRYPTOPP_GET_BYTE_AS_BYTE(x, y) byte((x)>>(8*(y)))
+
+template <class T>
+unsigned int Parity(T value)
+{
+	for (unsigned int i=8*sizeof(value)/2; i>0; i/=2)
+		value ^= value >> i;
+	return (unsigned int)value&1;
+}
+
+template <class T>
+unsigned int BytePrecision(const T &value)
+{
+	if (!value)
+		return 0;
+
+	unsigned int l=0, h=8*sizeof(value);
+
+	while (h-l > 8)
+	{
+		unsigned int t = (l+h)/2;
+		if (value >> t)
+			l = t;
+		else
+			h = t;
+	}
+
+	return h/8;
+}
+
+template <class T>
+unsigned int BitPrecision(const T &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;
+}
+
+template <class T>
+inline T Crop(T value, size_t size)
+{
+	if (size < 8*sizeof(value))
+    	return T(value & ((T(1) << size) - 1));
+	else
+		return value;
+}
+
+template <class T1, class T2>
+inline bool SafeConvert(T1 from, T2 &to)
+{
+	to = (T2)from;
+	if (from != to || (from > 0) != (to > 0))
+		return false;
+	return true;
+}
+
+inline size_t BitsToBytes(size_t bitCount)
+{
+	return ((bitCount+7)/(8));
+}
+
+inline size_t BytesToWords(size_t byteCount)
+{
+	return ((byteCount+WORD_SIZE-1)/WORD_SIZE);
+}
+
+inline size_t BitsToWords(size_t bitCount)
+{
+	return ((bitCount+WORD_BITS-1)/(WORD_BITS));
+}
+
+inline size_t BitsToDwords(size_t bitCount)
+{
+	return ((bitCount+2*WORD_BITS-1)/(2*WORD_BITS));
+}
+
+CRYPTOPP_DLL void CRYPTOPP_API xorbuf(byte *buf, const byte *mask, size_t count);
+CRYPTOPP_DLL void CRYPTOPP_API xorbuf(byte *output, const byte *input, const byte *mask, size_t count);
+
+CRYPTOPP_DLL bool CRYPTOPP_API VerifyBufsEqual(const byte *buf1, const byte *buf2, size_t count);
+
+template <class T>
+inline bool IsPowerOf2(const T &n)
+{
+	return n > 0 && (n & (n-1)) == 0;
+}
+
+template <class T1, class T2>
+inline T2 ModPowerOf2(const T1 &a, const T2 &b)
+{
+	assert(IsPowerOf2(b));
+	return T2(a) & (b-1);
+}
+
+template <class T1, class T2>
+inline T1 RoundDownToMultipleOf(const T1 &n, const T2 &m)
+{
+	if (IsPowerOf2(m))
+		return n - ModPowerOf2(n, m);
+	else
+		return n - n%m;
+}
+
+template <class T1, class T2>
+inline T1 RoundUpToMultipleOf(const T1 &n, const T2 &m)
+{
+	if (n+m-1 < n)
+		throw InvalidArgument("RoundUpToMultipleOf: integer overflow");
+	return RoundDownToMultipleOf(n+m-1, m);
+}
+
+template <class T>
+inline unsigned int GetAlignmentOf(T *dummy=NULL)	// VC60 workaround
+{
+#ifdef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
+	if (sizeof(T) < 16)
+		return 1;
+#endif
+
+#if (_MSC_VER >= 1300)
+	return __alignof(T);
+#elif defined(__GNUC__)
+	return __alignof__(T);
+#elif CRYPTOPP_BOOL_SLOW_WORD64
+	return UnsignedMin(4U, sizeof(T));
+#else
+	return sizeof(T);
+#endif
+}
+
+inline bool IsAlignedOn(const void *p, unsigned int alignment)
+{
+	return alignment==1 || (IsPowerOf2(alignment) ? ModPowerOf2((size_t)p, alignment) == 0 : (size_t)p % alignment == 0);
+}
+
+template <class T>
+inline bool IsAligned(const void *p, T *dummy=NULL)	// VC60 workaround
+{
+	return IsAlignedOn(p, GetAlignmentOf<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>
+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(const T1 &a, const T2 &b)
+{
+	return T1((a > b) ? (a - b) : 0);
+}
+
+template <class T>
+inline CipherDir GetCipherDir(const T &obj)
+{
+	return obj.IsForwardTransformation() ? ENCRYPTION : DECRYPTION;
+}
+
+CRYPTOPP_DLL void CRYPTOPP_API CallNewHandler();
+
+inline void IncrementCounterByOne(byte *inout, unsigned int s)
+{
+	for (int i=s-1, carry=1; i>=0 && carry; i--)
+		carry = !++inout[i];
+}
+
+inline void IncrementCounterByOne(byte *output, const byte *input, unsigned int s)
+{
+	int i, carry;
+	for (i=s-1, carry=1; i>=0 && carry; i--)
+		carry = ((output[i] = input[i]+1) == 0);
+	memcpy_s(output, s, input, i+1);
+}
+
+// ************** rotate functions ***************
+
+template <class T> inline T rotlFixed(T x, unsigned int y)
+{
+	assert(y < sizeof(T)*8);
+	return T((x<<y) | (x>>(sizeof(T)*8-y)));
+}
+
+template <class T> inline T rotrFixed(T x, unsigned int y)
+{
+	assert(y < sizeof(T)*8);
+	return T((x>>y) | (x<<(sizeof(T)*8-y)));
+}
+
+template <class T> inline T rotlVariable(T x, unsigned int y)
+{
+	assert(y < sizeof(T)*8);
+	return T((x<<y) | (x>>(sizeof(T)*8-y)));
+}
+
+template <class T> inline T rotrVariable(T x, unsigned int y)
+{
+	assert(y < sizeof(T)*8);
+	return T((x>>y) | (x<<(sizeof(T)*8-y)));
+}
+
+template <class T> inline T rotlMod(T x, unsigned int y)
+{
+	y %= sizeof(T)*8;
+	return T((x<<y) | (x>>(sizeof(T)*8-y)));
+}
+
+template <class T> inline T rotrMod(T x, unsigned int y)
+{
+	y %= sizeof(T)*8;
+	return T((x>>y) | (x<<(sizeof(T)*8-y)));
+}
+
+#ifdef _MSC_VER
+
+template<> inline word32 rotlFixed<word32>(word32 x, unsigned int y)
+{
+	assert(y < 8*sizeof(x));
+	return y ? _lrotl(x, y) : x;
+}
+
+template<> inline word32 rotrFixed<word32>(word32 x, unsigned int y)
+{
+	assert(y < 8*sizeof(x));
+	return y ? _lrotr(x, y) : x;
+}
+
+template<> inline word32 rotlVariable<word32>(word32 x, unsigned int y)
+{
+	assert(y < 8*sizeof(x));
+	return _lrotl(x, y);
+}
+
+template<> inline word32 rotrVariable<word32>(word32 x, unsigned int y)
+{
+	assert(y < 8*sizeof(x));
+	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 _MSC_VER
+
+#if _MSC_VER >= 1300 && !defined(__INTEL_COMPILER)
+// Intel C++ Compiler 10.0 calls a function instead of using the rotate instruction when using these instructions
+
+template<> inline word64 rotlFixed<word64>(word64 x, unsigned int y)
+{
+	assert(y < 8*sizeof(x));
+	return y ? _rotl64(x, y) : x;
+}
+
+template<> inline word64 rotrFixed<word64>(word64 x, unsigned int y)
+{
+	assert(y < 8*sizeof(x));
+	return y ? _rotr64(x, y) : x;
+}
+
+template<> inline word64 rotlVariable<word64>(word64 x, unsigned int y)
+{
+	assert(y < 8*sizeof(x));
+	return _rotl64(x, y);
+}
+
+template<> inline word64 rotrVariable<word64>(word64 x, unsigned int y)
+{
+	assert(y < 8*sizeof(x));
+	return _rotr64(x, y);
+}
+
+template<> inline word64 rotlMod<word64>(word64 x, unsigned int y)
+{
+	return _rotl64(x, y);
+}
+
+template<> inline word64 rotrMod<word64>(word64 x, unsigned int y)
+{
+	return _rotr64(x, y);
+}
+
+#endif // #if _MSC_VER >= 1310
+
+#if _MSC_VER >= 1400 && !defined(__INTEL_COMPILER)
+// Intel C++ Compiler 10.0 gives undefined externals with these
+
+template<> inline word16 rotlFixed<word16>(word16 x, unsigned int y)
+{
+	assert(y < 8*sizeof(x));
+	return y ? _rotl16(x, y) : x;
+}
+
+template<> inline word16 rotrFixed<word16>(word16 x, unsigned int y)
+{
+	assert(y < 8*sizeof(x));
+	return y ? _rotr16(x, y) : x;
+}
+
+template<> inline word16 rotlVariable<word16>(word16 x, unsigned int y)
+{
+	assert(y < 8*sizeof(x));
+	return _rotl16(x, y);
+}
+
+template<> inline word16 rotrVariable<word16>(word16 x, unsigned int y)
+{
+	assert(y < 8*sizeof(x));
+	return _rotr16(x, y);
+}
+
+template<> inline word16 rotlMod<word16>(word16 x, unsigned int y)
+{
+	return _rotl16(x, y);
+}
+
+template<> inline word16 rotrMod<word16>(word16 x, unsigned int y)
+{
+	return _rotr16(x, y);
+}
+
+template<> inline byte rotlFixed<byte>(byte x, unsigned int y)
+{
+	assert(y < 8*sizeof(x));
+	return y ? _rotl8(x, y) : x;
+}
+
+template<> inline byte rotrFixed<byte>(byte x, unsigned int y)
+{
+	assert(y < 8*sizeof(x));
+	return y ? _rotr8(x, y) : x;
+}
+
+template<> inline byte rotlVariable<byte>(byte x, unsigned int y)
+{
+	assert(y < 8*sizeof(x));
+	return _rotl8(x, y);
+}
+
+template<> inline byte rotrVariable<byte>(byte x, unsigned int y)
+{
+	assert(y < 8*sizeof(x));
+	return _rotr8(x, y);
+}
+
+template<> inline byte rotlMod<byte>(byte x, unsigned int y)
+{
+	return _rotl8(x, y);
+}
+
+template<> inline byte rotrMod<byte>(byte x, unsigned int y)
+{
+	return _rotr8(x, y);
+}
+
+#endif // #if _MSC_VER >= 1400
+
+#if (defined(__MWERKS__) && TARGET_CPU_PPC)
+
+template<> inline word32 rotlFixed<word32>(word32 x, unsigned int y)
+{
+	assert(y < 32);
+	return y ? __rlwinm(x,y,0,31) : x;
+}
+
+template<> inline word32 rotrFixed<word32>(word32 x, unsigned int y)
+{
+	assert(y < 32);
+	return y ? __rlwinm(x,32-y,0,31) : x;
+}
+
+template<> inline word32 rotlVariable<word32>(word32 x, unsigned int y)
+{
+	assert(y < 32);
+	return (__rlwnm(x,y,0,31));
+}
+
+template<> inline word32 rotrVariable<word32>(word32 x, unsigned int y)
+{
+	assert(y < 32);
+	return (__rlwnm(x,32-y,0,31));
+}
+
+template<> inline word32 rotlMod<word32>(word32 x, unsigned int y)
+{
+	return (__rlwnm(x,y,0,31));
+}
+
+template<> inline word32 rotrMod<word32>(word32 x, unsigned int y)
+{
+	return (__rlwnm(x,32-y,0,31));
+}
+
+#endif // #if (defined(__MWERKS__) && TARGET_CPU_PPC)
+
+// ************** 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)
+{
+#ifdef CRYPTOPP_BYTESWAP_AVAILABLE
+	return bswap_16(value);
+#elif defined(_MSC_VER) && _MSC_VER >= 1300
+	return _byteswap_ushort(value);
+#else
+	return rotlFixed(value, 8U);
+#endif
+}
+
+inline word32 ByteReverse(word32 value)
+{
+#if defined(__GNUC__) && defined(CRYPTOPP_X86_ASM_AVAILABLE)
+	__asm__ ("bswap %0" : "=r" (value) : "0" (value));
+	return value;
+#elif defined(CRYPTOPP_BYTESWAP_AVAILABLE)
+	return bswap_32(value);
+#elif defined(__MWERKS__) && TARGET_CPU_PPC
+	return (word32)__lwbrx(&value,0);
+#elif _MSC_VER >= 1400 || (_MSC_VER >= 1300 && !defined(_DLL))
+	return _byteswap_ulong(value);
+#elif CRYPTOPP_FAST_ROTATE(32)
+	// 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
+}
+
+inline word64 ByteReverse(word64 value)
+{
+#if defined(__GNUC__) && defined(CRYPTOPP_X86_ASM_AVAILABLE) && defined(__x86_64__)
+	__asm__ ("bswap %0" : "=r" (value) : "0" (value));
+	return value;
+#elif defined(CRYPTOPP_BYTESWAP_AVAILABLE)
+	return bswap_64(value);
+#elif defined(_MSC_VER) && _MSC_VER >= 1300
+	return _byteswap_uint64(value);
+#elif CRYPTOPP_BOOL_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
+}
+
+inline byte BitReverse(byte value)
+{
+	value = ((value & 0xAA) >> 1) | ((value & 0x55) << 1);
+	value = ((value & 0xCC) >> 2) | ((value & 0x33) << 2);
+	return rotlFixed(value, 4U);
+}
+
+inline word16 BitReverse(word16 value)
+{
+	value = ((value & 0xAAAA) >> 1) | ((value & 0x5555) << 1);
+	value = ((value & 0xCCCC) >> 2) | ((value & 0x3333) << 2);
+	value = ((value & 0xF0F0) >> 4) | ((value & 0x0F0F) << 4);
+	return ByteReverse(value);
+}
+
+inline word32 BitReverse(word32 value)
+{
+	value = ((value & 0xAAAAAAAA) >> 1) | ((value & 0x55555555) << 1);
+	value = ((value & 0xCCCCCCCC) >> 2) | ((value & 0x33333333) << 2);
+	value = ((value & 0xF0F0F0F0) >> 4) | ((value & 0x0F0F0F0F) << 4);
+	return ByteReverse(value);
+}
+
+inline word64 BitReverse(word64 value)
+{
+#if CRYPTOPP_BOOL_SLOW_WORD64
+	return (word64(BitReverse(word32(value))) << 32) | BitReverse(word32(value>>32));
+#else
+	value = ((value & W64LIT(0xAAAAAAAAAAAAAAAA)) >> 1) | ((value & W64LIT(0x5555555555555555)) << 1);
+	value = ((value & W64LIT(0xCCCCCCCCCCCCCCCC)) >> 2) | ((value & W64LIT(0x3333333333333333)) << 2);
+	value = ((value & W64LIT(0xF0F0F0F0F0F0F0F0)) >> 4) | ((value & W64LIT(0x0F0F0F0F0F0F0F0F)) << 4);
+	return ByteReverse(value);
+#endif
+}
+
+template <class T>
+inline T BitReverse(T value)
+{
+	if (sizeof(T) == 1)
+		return (T)BitReverse((byte)value);
+	else if (sizeof(T) == 2)
+		return (T)BitReverse((word16)value);
+	else if (sizeof(T) == 4)
+		return (T)BitReverse((word32)value);
+	else
+	{
+		assert(sizeof(T) == 8);
+		return (T)BitReverse((word64)value);
+	}
+}
+
+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, size_t byteCount)
+{
+	assert(byteCount % sizeof(T) == 0);
+	size_t count = byteCount/sizeof(T);
+	for (size_t i=0; i<count; i++)
+		out[i] = ByteReverse(in[i]);
+}
+
+template <class T>
+inline void ConditionalByteReverse(ByteOrder order, T *out, const T *in, size_t byteCount)
+{
+	if (!NativeByteOrderIs(order))
+		ByteReverse(out, in, byteCount);
+	else if (in != out)
+		memcpy_s(out, byteCount, in, byteCount);
+}
+
+template <class T>
+inline void GetUserKey(ByteOrder order, T *out, size_t outlen, const byte *in, size_t inlen)
+{
+	const size_t U = sizeof(T);
+	assert(inlen <= outlen*U);
+	memcpy_s(out, outlen*U, in, inlen);
+	memset_z((byte *)out+inlen, 0, outlen*U-inlen);
+	ConditionalByteReverse(order, out, out, RoundUpToMultipleOf(inlen, U));
+}
+
+#ifndef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
+inline byte UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, const byte *)
+{
+	return block[0];
+}
+
+inline word16 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, const word16 *)
+{
+	return (order == BIG_ENDIAN_ORDER)
+		? block[1] | (block[0] << 8)
+		: block[0] | (block[1] << 8);
+}
+
+inline word32 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, const word32 *)
+{
+	return (order == BIG_ENDIAN_ORDER)
+		? word32(block[3]) | (word32(block[2]) << 8) | (word32(block[1]) << 16) | (word32(block[0]) << 24)
+		: word32(block[0]) | (word32(block[1]) << 8) | (word32(block[2]) << 16) | (word32(block[3]) << 24);
+}
+
+inline word64 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, const word64 *)
+{
+	return (order == BIG_ENDIAN_ORDER)
+		?
+		(word64(block[7]) |
+		(word64(block[6]) <<  8) |
+		(word64(block[5]) << 16) |
+		(word64(block[4]) << 24) |
+		(word64(block[3]) << 32) |
+		(word64(block[2]) << 40) |
+		(word64(block[1]) << 48) |
+		(word64(block[0]) << 56))
+		:
+		(word64(block[0]) |
+		(word64(block[1]) <<  8) |
+		(word64(block[2]) << 16) |
+		(word64(block[3]) << 24) |
+		(word64(block[4]) << 32) |
+		(word64(block[5]) << 40) |
+		(word64(block[6]) << 48) |
+		(word64(block[7]) << 56));
+}
+
+inline void UnalignedPutWordNonTemplate(ByteOrder order, byte *block, byte value, const byte *xorBlock)
+{
+	block[0] = xorBlock ? (value ^ xorBlock[0]) : value;
+}
+
+inline void UnalignedPutWordNonTemplate(ByteOrder order, byte *block, word16 value, const byte *xorBlock)
+{
+	if (order == BIG_ENDIAN_ORDER)
+	{
+		if (xorBlock)
+		{
+			block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
+			block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
+		}
+		else
+		{
+			block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
+			block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
+		}
+	}
+	else
+	{
+		if (xorBlock)
+		{
+			block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
+			block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
+		}
+		else
+		{
+			block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
+			block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
+		}
+	}
+}
+
+inline void UnalignedPutWordNonTemplate(ByteOrder order, byte *block, word32 value, const byte *xorBlock)
+{
+	if (order == BIG_ENDIAN_ORDER)
+	{
+		if (xorBlock)
+		{
+			block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 3);
+			block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 2);
+			block[2] = xorBlock[2] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
+			block[3] = xorBlock[3] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
+		}
+		else
+		{
+			block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 3);
+			block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 2);
+			block[2] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
+			block[3] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
+		}
+	}
+	else
+	{
+		if (xorBlock)
+		{
+			block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
+			block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
+			block[2] = xorBlock[2] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 2);
+			block[3] = xorBlock[3] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 3);
+		}
+		else
+		{
+			block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
+			block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
+			block[2] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 2);
+			block[3] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 3);
+		}
+	}
+}
+
+inline void UnalignedPutWordNonTemplate(ByteOrder order, byte *block, word64 value, const byte *xorBlock)
+{
+	if (order == BIG_ENDIAN_ORDER)
+	{
+		if (xorBlock)
+		{
+			block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 7);
+			block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 6);
+			block[2] = xorBlock[2] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 5);
+			block[3] = xorBlock[3] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 4);
+			block[4] = xorBlock[4] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 3);
+			block[5] = xorBlock[5] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 2);
+			block[6] = xorBlock[6] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
+			block[7] = xorBlock[7] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
+		}
+		else
+		{
+			block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 7);
+			block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 6);
+			block[2] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 5);
+			block[3] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 4);
+			block[4] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 3);
+			block[5] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 2);
+			block[6] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
+			block[7] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
+		}
+	}
+	else
+	{
+		if (xorBlock)
+		{
+			block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
+			block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
+			block[2] = xorBlock[2] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 2);
+			block[3] = xorBlock[3] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 3);
+			block[4] = xorBlock[4] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 4);
+			block[5] = xorBlock[5] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 5);
+			block[6] = xorBlock[6] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 6);
+			block[7] = xorBlock[7] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 7);
+		}
+		else
+		{
+			block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
+			block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
+			block[2] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 2);
+			block[3] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 3);
+			block[4] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 4);
+			block[5] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 5);
+			block[6] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 6);
+			block[7] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 7);
+		}
+	}
+}
+#endif	// #ifndef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
+
+template <class T>
+inline T GetWord(bool assumeAligned, ByteOrder order, const byte *block)
+{
+#ifndef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
+	if (!assumeAligned)
+		return UnalignedGetWordNonTemplate(order, block, (T*)NULL);
+	assert(IsAligned<T>(block));
+#endif
+	return ConditionalByteReverse(order, *reinterpret_cast<const T *>(block));
+}
+
+template <class T>
+inline void GetWord(bool assumeAligned, ByteOrder order, T &result, const byte *block)
+{
+	result = GetWord<T>(assumeAligned, order, block);
+}
+
+template <class T>
+inline void PutWord(bool assumeAligned, ByteOrder order, byte *block, T value, const byte *xorBlock = NULL)
+{
+#ifndef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
+	if (!assumeAligned)
+		return UnalignedPutWordNonTemplate(order, block, value, xorBlock);
+	assert(IsAligned<T>(block));
+	assert(IsAligned<T>(xorBlock));
+#endif
+	*reinterpret_cast<T *>(block) = ConditionalByteReverse(order, value) ^ (xorBlock ? *reinterpret_cast<const T *>(xorBlock) : 0);
+}
+
+template <class T, class B, bool A=false>
+class GetBlock
+{
+public:
+	GetBlock(const void *block)
+		: m_block((const byte *)block) {}
+
+	template <class U>
+	inline GetBlock<T, B, A> & operator()(U &x)
+	{
+		CRYPTOPP_COMPILE_ASSERT(sizeof(U) >= sizeof(T));
+		x = GetWord<T>(A, B::ToEnum(), m_block);
+		m_block += sizeof(T);
+		return *this;
+	}
+
+private:
+	const byte *m_block;
+};
+
+template <class T, class B, bool A=false>
+class PutBlock
+{
+public:
+	PutBlock(const void *xorBlock, void *block)
+		: m_xorBlock((const byte *)xorBlock), m_block((byte *)block) {}
+
+	template <class U>
+	inline PutBlock<T, B, A> & operator()(U x)
+	{
+		PutWord(A, B::ToEnum(), m_block, (T)x, m_xorBlock);
+		m_block += sizeof(T);
+		if (m_xorBlock)
+			m_xorBlock += sizeof(T);
+		return *this;
+	}
+
+private:
+	const byte *m_xorBlock;
+	byte *m_block;
+};
+
+template <class T, class B, bool GA=false, bool PA=false>
+struct BlockGetAndPut
+{
+	// function needed because of C++ grammatical ambiguity between expression-statements and declarations
+	static inline GetBlock<T, B, GA> Get(const void *block) {return GetBlock<T, B, GA>(block);}
+	typedef PutBlock<T, B, PA> Put;
+};
+
+template <class T>
+std::string WordToString(T value, ByteOrder order = BIG_ENDIAN_ORDER)
+{
+	if (!NativeByteOrderIs(order))
+		value = ByteReverse(value);
+
+	return std::string((char *)&value, sizeof(value));
+}
+
+template <class T>
+T StringToWord(const std::string &str, ByteOrder order = BIG_ENDIAN_ORDER)
+{
+	T value = 0;
+	memcpy_s(&value, sizeof(value), str.data(), UnsignedMin(str.size(), sizeof(value)));
+	return NativeByteOrderIs(order) ? value : ByteReverse(value);
+}
+
+// ************** help remove warning on g++ ***************
+
+template <bool overflow> struct SafeShifter;
+
+template<> struct SafeShifter<true>
+{
+	template <class T>
+	static inline T RightShift(T value, unsigned int bits)
+	{
+		return 0;
+	}
+
+	template <class T>
+	static inline T LeftShift(T value, unsigned int bits)
+	{
+		return 0;
+	}
+};
+
+template<> struct SafeShifter<false>
+{
+	template <class T>
+	static inline T RightShift(T value, unsigned int bits)
+	{
+		return value >> bits;
+	}
+
+	template <class T>
+	static inline T LeftShift(T value, unsigned int bits)
+	{
+		return value << bits;
+	}
+};
+
+template <unsigned int bits, class T>
+inline T SafeRightShift(T value)
+{
+	return SafeShifter<(bits>=(8*sizeof(T)))>::RightShift(value, bits);
+}
+
+template <unsigned int bits, class T>
+inline T SafeLeftShift(T value)
+{
+	return SafeShifter<(bits>=(8*sizeof(T)))>::LeftShift(value, bits);
+}
+
+// ************** use one buffer for multiple data members ***************
+
+#define CRYPTOPP_BLOCK_1(n, t, s) t* m_##n() {return (t *)(m_aggregate+0);}     size_t SS1() {return       sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
+#define CRYPTOPP_BLOCK_2(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS1());} size_t SS2() {return SS1()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
+#define CRYPTOPP_BLOCK_3(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS2());} size_t SS3() {return SS2()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
+#define CRYPTOPP_BLOCK_4(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS3());} size_t SS4() {return SS3()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
+#define CRYPTOPP_BLOCK_5(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS4());} size_t SS5() {return SS4()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
+#define CRYPTOPP_BLOCK_6(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS5());} size_t SS6() {return SS5()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
+#define CRYPTOPP_BLOCK_7(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS6());} size_t SS7() {return SS6()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
+#define CRYPTOPP_BLOCK_8(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS7());} size_t SS8() {return SS7()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
+#define CRYPTOPP_BLOCKS_END(i) size_t SST() {return SS##i();} void AllocateBlocks() {m_aggregate.New(SST());} AlignedSecByteBlock m_aggregate;
+
+NAMESPACE_END
+
+#endif
new file mode 100644
--- /dev/null
+++ b/cryptopp/pch.h
@@ -0,0 +1,21 @@
+#ifndef CRYPTOPP_PCH_H
+#define CRYPTOPP_PCH_H
+
+#ifdef CRYPTOPP_GENERATE_X64_MASM
+
+	#include "cpu.h"
+
+#else
+
+	#include "config.h"
+
+	#ifdef USE_PRECOMPILED_HEADERS
+		#include "simple.h"
+		#include "secblock.h"
+		#include "misc.h"
+		#include "smartptr.h"
+	#endif
+
+#endif
+
+#endif
new file mode 100644
--- /dev/null
+++ b/cryptopp/secblock.h
@@ -0,0 +1,500 @@
+// 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 <assert.h>
+
+#if defined(CRYPTOPP_MEMALIGN_AVAILABLE) || defined(CRYPTOPP_MM_MALLOC_AVAILABLE) || defined(QNX)
+	#include <malloc.h>
+#else
+	#include <stdlib.h>
+#endif
+
+NAMESPACE_BEGIN(CryptoPP)
+
+// ************** secure memory allocation ***************
+
+template<class T>
+class AllocatorBase
+{
+public:
+	typedef T value_type;
+	typedef size_t size_type;
+#ifdef CRYPTOPP_MSVCRT6
+	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(0)/sizeof(T);}	// switch to std::numeric_limits<T>::max later
+
+protected:
+	static void CheckSize(size_t n)
+	{
+		if (n > ~size_t(0) / sizeof(T))
+			throw InvalidArgument("AllocatorBase: requested size would cause integer overflow");
+	}
+};
+
+#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;
+
+#if defined(_MSC_VER) && (_MSC_VER < 1300)
+// this pragma causes an internal compiler error if placed immediately before std::swap(a, b)
+#pragma warning(push)
+#pragma warning(disable: 4700)	// VC60 workaround: don't know how to get rid of this warning
+#endif
+
+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_s(newPointer, sizeof(T)*newSize, p, sizeof(T)*STDMIN(oldSize, newSize));
+		a.deallocate(p, oldSize);
+		return newPointer;
+	}
+	else
+	{
+		a.deallocate(p, oldSize);
+		return a.allocate(newSize, NULL);
+	}
+}
+
+#if defined(_MSC_VER) && (_MSC_VER < 1300)
+#pragma warning(pop)
+#endif
+
+template <class T, bool T_Align16 = false>
+class AllocatorWithCleanup : public AllocatorBase<T>
+{
+public:
+	CRYPTOPP_INHERIT_ALLOCATOR_TYPES
+
+	pointer allocate(size_type n, const void * = NULL)
+	{
+		CheckSize(n);
+		if (n == 0)
+			return NULL;
+
+		if (CRYPTOPP_BOOL_ALIGN16_ENABLED && T_Align16 && n*sizeof(T) >= 16)
+		{
+			byte *p;
+		#ifdef CRYPTOPP_MM_MALLOC_AVAILABLE
+			while (!(p = (byte *)_mm_malloc(sizeof(T)*n, 16)))
+		#elif defined(CRYPTOPP_MEMALIGN_AVAILABLE)
+			while (!(p = (byte *)memalign(16, sizeof(T)*n)))
+		#elif defined(CRYPTOPP_MALLOC_ALIGNMENT_IS_16)
+			while (!(p = (byte *)malloc(sizeof(T)*n)))
+		#else
+			while (!(p = (byte *)malloc(sizeof(T)*n + 16)))
+		#endif
+				CallNewHandler();
+
+		#ifdef CRYPTOPP_NO_ALIGNED_ALLOC
+			size_t adjustment = 16-((size_t)p%16);
+			p += adjustment;
+			p[-1] = (byte)adjustment;
+		#endif
+
+			assert(IsAlignedOn(p, 16));
+			return (pointer)p;
+		}
+
+		pointer p;
+		while (!(p = (pointer)malloc(sizeof(T)*n)))
+			CallNewHandler();
+		return p;
+	}
+
+	void deallocate(void *p, size_type n)
+	{
+		memset_z(p, 0, n*sizeof(T));
+
+		if (CRYPTOPP_BOOL_ALIGN16_ENABLED && T_Align16 && n*sizeof(T) >= 16)
+		{
+		#ifdef CRYPTOPP_MM_MALLOC_AVAILABLE
+			_mm_free(p);
+		#elif defined(CRYPTOPP_NO_ALIGNED_ALLOC)
+			p = (byte *)p - ((byte *)p)[-1];
+			free(p);
+		#else
+			free(p);
+		#endif
+			return;
+		}
+
+		free(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, T_Align16> other; };
+#if _MSC_VER >= 1500
+	AllocatorWithCleanup() {}
+	template <class U, bool A> AllocatorWithCleanup(const AllocatorWithCleanup<U, A> &) {}
+#endif
+};
+
+CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<byte>;
+CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word16>;
+CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word32>;
+CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word64>;
+#if CRYPTOPP_BOOL_X86
+CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word, true>;	// for Integer
+#endif
+
+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);
+	}
+
+	size_type max_size() const {return 0;}
+};
+
+// This allocator can't be used with standard collections because
+// they require that all objects of the same allocator type are equivalent.
+// So this is for use with SecBlock only.
+template <class T, size_t S, class A = NullAllocator<T>, bool T_Align16 = false>
+class FixedSizeAllocatorWithCleanup : public AllocatorBase<T>
+{
+public:
+	CRYPTOPP_INHERIT_ALLOCATOR_TYPES
+
+	FixedSizeAllocatorWithCleanup() : m_allocated(false) {}
+
+	pointer allocate(size_type n)
+	{
+		assert(IsAlignedOn(m_array, 8));
+
+		if (n <= S && !m_allocated)
+		{
+			m_allocated = true;
+			return GetAlignedArray();
+		}
+		else
+			return m_fallbackAllocator.allocate(n);
+	}
+
+	pointer allocate(size_type n, const void *hint)
+	{
+		if (n <= S && !m_allocated)
+		{
+			m_allocated = true;
+			return GetAlignedArray();
+		}
+		else
+			return m_fallbackAllocator.allocate(n, hint);
+	}
+
+	void deallocate(void *p, size_type n)
+	{
+		if (p == GetAlignedArray())
+		{
+			assert(n <= S);
+			assert(m_allocated);
+			m_allocated = false;
+			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 (p == GetAlignedArray() && newSize <= S)
+		{
+			assert(oldSize <= S);
+			if (oldSize > newSize)
+				memset(p + newSize, 0, (oldSize-newSize)*sizeof(T));
+			return p;
+		}
+
+		pointer newPointer = allocate(newSize, NULL);
+		if (preserve)
+			memcpy(newPointer, p, sizeof(T)*STDMIN(oldSize, newSize));
+		deallocate(p, oldSize);
+		return newPointer;
+	}
+
+	size_type max_size() const {return STDMAX(m_fallbackAllocator.max_size(), S);}
+
+private:
+#ifdef __BORLANDC__
+	T* GetAlignedArray() {return m_array;}
+	T m_array[S];
+#else
+	T* GetAlignedArray() {return (CRYPTOPP_BOOL_ALIGN16_ENABLED && T_Align16) ? (T*)(((byte *)m_array) + (0-(size_t)m_array)%16) : m_array;}
+	CRYPTOPP_ALIGN_DATA(8) T m_array[(CRYPTOPP_BOOL_ALIGN16_ENABLED && T_Align16) ? S+8/sizeof(T) : S];
+#endif
+	A m_fallbackAllocator;
+	bool m_allocated;
+};
+
+//! a block of memory allocated using A
+template <class T, class A = AllocatorWithCleanup<T> >
+class SecBlock
+{
+public:
+	typedef typename A::value_type value_type;
+	typedef typename A::pointer iterator;
+	typedef typename A::const_pointer const_iterator;
+	typedef typename A::size_type size_type;
+
+	explicit SecBlock(size_type 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_s(m_ptr, m_size*sizeof(T), t.m_ptr, m_size*sizeof(T));}
+	SecBlock(const T *t, size_type len)
+		: m_size(len)
+	{
+		m_ptr = m_alloc.allocate(len, NULL);
+		if (t == NULL)
+			memset_z(m_ptr, 0, len*sizeof(T));
+		else
+			memcpy(m_ptr, t, len*sizeof(T));
+	}
+
+	~SecBlock()
+		{m_alloc.deallocate(m_ptr, m_size);}
+
+#ifdef __BORLANDC__
+	operator T *() const
+		{return (T*)m_ptr;}
+#else
+	operator const void *() const
+		{return m_ptr;}
+	operator void *()
+		{return m_ptr;}
+
+	operator const T *() const
+		{return m_ptr;}
+	operator T *()
+		{return m_ptr;}
+#endif
+
+//	T *operator +(size_type offset)
+//		{return m_ptr+offset;}
+
+//	const T *operator +(size_type offset) const
+//		{return m_ptr+offset;}
+
+//	T& operator[](size_type index)
+//		{assert(index >= 0 && index < m_size); return m_ptr[index];}
+
+//	const T& operator[](size_type index) const
+//		{assert(index >= 0 && index < m_size); return m_ptr[index];}
+
+	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;}
+
+	byte * BytePtr() {return (byte *)m_ptr;}
+	const byte * BytePtr() const {return (const byte *)m_ptr;}
+	size_type SizeInBytes() const {return m_size*sizeof(T);}
+
+	//! set contents and size
+	void Assign(const T *t, size_type len)
+	{
+		New(len);
+		memcpy_s(m_ptr, m_size*sizeof(T), t, len*sizeof(T));
+	}
+
+	//! copy contents and size from another SecBlock
+	void Assign(const SecBlock<T, A> &t)
+	{
+		New(t.m_size);
+		memcpy_s(m_ptr, m_size*sizeof(T), t.m_ptr, m_size*sizeof(T));
+	}
+
+	SecBlock<T, A>& operator=(const SecBlock<T, A> &t)
+	{
+		Assign(t);
+		return *this;
+	}
+
+	// append to this object
+	SecBlock<T, A>& operator+=(const SecBlock<T, A> &t)
+	{
+		size_type oldSize = m_size;
+		Grow(m_size+t.m_size);
+		memcpy_s(m_ptr+oldSize, m_size*sizeof(T), t.m_ptr, t.m_size*sizeof(T));
+		return *this;
+	}
+
+	// append operator
+	SecBlock<T, A> operator+(const SecBlock<T, A> &t)
+	{
+		SecBlock<T, A> result(m_size+t.m_size);
+		memcpy_s(result.m_ptr, result.m_size*sizeof(T), m_ptr, m_size*sizeof(T));
+		memcpy_s(result.m_ptr+m_size, t.m_size*sizeof(T), t.m_ptr, t.m_size*sizeof(T));
+		return result;
+	}
+
+	bool operator==(const SecBlock<T, A> &t) const
+	{
+		return m_size == t.m_size && VerifyBufsEqual(m_ptr, t.m_ptr, m_size*sizeof(T));
+	}
+
+	bool operator!=(const SecBlock<T, A> &t) const
+	{
+		return !operator==(t);
+	}
+
+	//! change size, without preserving contents
+	void New(size_type newSize)
+	{
+		m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, false);
+		m_size = newSize;
+	}
+
+	//! change size and set contents to 0
+	void CleanNew(size_type newSize)
+	{
+		New(newSize);
+		memset_z(m_ptr, 0, m_size*sizeof(T));
+	}
+
+	//! change size only if newSize > current size. contents are preserved
+	void Grow(size_type newSize)
+	{
+		if (newSize > m_size)
+		{
+			m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
+			m_size = newSize;
+		}
+	}
+
+	//! change size only if newSize > current size. contents are preserved and additional area is set to 0
+	void CleanGrow(size_type 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;
+		}
+	}
+
+	//! change size and preserve contents
+	void resize(size_type newSize)
+	{
+		m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
+		m_size = newSize;
+	}
+
+	//! swap contents and size with another SecBlock
+	void 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);
+	}
+
+//private:
+	A m_alloc;
+	size_type m_size;
+	T *m_ptr;
+};
+
+typedef SecBlock<byte> SecByteBlock;
+typedef SecBlock<byte, AllocatorWithCleanup<byte, true> > AlignedSecByteBlock;
+typedef SecBlock<word> SecWordBlock;
+
+//! a SecBlock with fixed size, allocated statically
+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, bool T_Align16 = true>
+class FixedSizeAlignedSecBlock : public FixedSizeSecBlock<T, S, FixedSizeAllocatorWithCleanup<T, S, NullAllocator<T>, T_Align16> >
+{
+};
+
+//! a SecBlock that preallocates size S statically, and uses the heap when this size is exceeded
+template <class T, unsigned int S, class A = FixedSizeAllocatorWithCleanup<T, S, AllocatorWithCleanup<T> > >
+class SecBlockWithHint : public SecBlock<T, A>
+{
+public:
+	explicit SecBlockWithHint(size_t size) : SecBlock<T, A>(size) {}
+};
+
+template<class T, bool A, class U, bool B>
+inline bool operator==(const CryptoPP::AllocatorWithCleanup<T, A>&, const CryptoPP::AllocatorWithCleanup<U, B>&) {return (true);}
+template<class T, bool A, class U, bool B>
+inline bool operator!=(const CryptoPP::AllocatorWithCleanup<T, A>&, const CryptoPP::AllocatorWithCleanup<U, B>&) {return (false);}
+
+NAMESPACE_END
+
+NAMESPACE_BEGIN(std)
+template <class T, class A>
+inline void swap(CryptoPP::SecBlock<T, A> &a, CryptoPP::SecBlock<T, A> &b)
+{
+	a.swap(b);
+}
+
+#if defined(_STLP_DONT_SUPPORT_REBIND_MEMBER_TEMPLATE) || (defined(_STLPORT_VERSION) && !defined(_STLP_MEMBER_TEMPLATE_CLASSES))
+// working for STLport 5.1.3 and MSVC 6 SP5
+template <class _Tp1, class _Tp2>
+inline CryptoPP::AllocatorWithCleanup<_Tp2>&
+__stl_alloc_rebind(CryptoPP::AllocatorWithCleanup<_Tp1>& __a, const _Tp2*)
+{
+	return (CryptoPP::AllocatorWithCleanup<_Tp2>&)(__a);
+}
+#endif
+
+NAMESPACE_END
+
+#endif
new file mode 100644
--- /dev/null
+++ b/cryptopp/sha.cpp
@@ -0,0 +1,899 @@
+// 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.
+
+// use "cl /EP /P /DCRYPTOPP_GENERATE_X64_MASM sha.cpp" to generate MASM code
+
+#include "pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+#ifndef CRYPTOPP_GENERATE_X64_MASM
+
+#include "sha.h"
+#include "misc.h"
+#include "cpu.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+// 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))
+
+void SHA1::InitState(HashWordType *state)
+{
+	state[0] = 0x67452301L;
+	state[1] = 0xEFCDAB89L;
+	state[2] = 0x98BADCFEL;
+	state[3] = 0x10325476L;
+	state[4] = 0xC3D2E1F0L;
+}
+
+#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 SHA1::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;
+}
+
+// end of Steve Reid's code
+
+// *************************************************************
+
+void SHA224::InitState(HashWordType *state)
+{
+	static const word32 s[8] = {0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4};
+	memcpy(state, s, sizeof(s));
+}
+
+void SHA256::InitState(HashWordType *state)
+{
+	static const word32 s[8] = {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};
+	memcpy(state, s, sizeof(s));
+}
+
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+CRYPTOPP_ALIGN_DATA(16) extern const word32 SHA256_K[64] CRYPTOPP_SECTION_ALIGN16 = {
+#else
+extern const word32 SHA256_K[64] = {
+#endif
+	0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
+	0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+	0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+	0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+	0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
+	0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+	0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
+	0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+	0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+	0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+	0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
+	0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+	0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
+	0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+	0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+	0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+};
+
+#endif // #ifndef CRYPTOPP_GENERATE_X64_MASM
+
+#if defined(CRYPTOPP_X86_ASM_AVAILABLE) || defined(CRYPTOPP_GENERATE_X64_MASM)
+
+#pragma warning(disable: 4731)	// frame pointer register 'ebp' modified by inline assembly code
+
+static void CRYPTOPP_FASTCALL X86_SHA256_HashBlocks(word32 *state, const word32 *data, size_t len
+#if defined(_MSC_VER) && (_MSC_VER == 1200)
+	, ...	// VC60 workaround: prevent VC 6 from inlining this function
+#endif
+	)
+{
+#if defined(_MSC_VER) && (_MSC_VER == 1200)
+	AS2(mov ecx, [state])
+	AS2(mov edx, [data])
+#endif
+
+	#define LOCALS_SIZE	8*4 + 16*4 + 4*WORD_SZ
+	#define H(i)		[BASE+ASM_MOD(1024+7-(i),8)*4]
+	#define G(i)		H(i+1)
+	#define F(i)		H(i+2)
+	#define E(i)		H(i+3)
+	#define D(i)		H(i+4)
+	#define C(i)		H(i+5)
+	#define B(i)		H(i+6)
+	#define A(i)		H(i+7)
+	#define Wt(i)		BASE+8*4+ASM_MOD(1024+15-(i),16)*4
+	#define Wt_2(i)		Wt((i)-2)
+	#define Wt_15(i)	Wt((i)-15)
+	#define Wt_7(i)		Wt((i)-7)
+	#define K_END		[BASE+8*4+16*4+0*WORD_SZ]
+	#define STATE_SAVE	[BASE+8*4+16*4+1*WORD_SZ]
+	#define DATA_SAVE	[BASE+8*4+16*4+2*WORD_SZ]
+	#define DATA_END	[BASE+8*4+16*4+3*WORD_SZ]
+	#define Kt(i)		WORD_REG(si)+(i)*4
+#if CRYPTOPP_BOOL_X86
+	#define BASE		esp+4
+#elif defined(__GNUC__)
+	#define BASE		r8
+#else
+	#define BASE		rsp
+#endif
+
+#define RA0(i, edx, edi)		\
+	AS2(	add edx, [Kt(i)]	)\
+	AS2(	add edx, [Wt(i)]	)\
+	AS2(	add edx, H(i)		)\
+
+#define RA1(i, edx, edi)
+
+#define RB0(i, edx, edi)
+
+#define RB1(i, edx, edi)	\
+	AS2(	mov AS_REG_7d, [Wt_2(i)]	)\
+	AS2(	mov edi, [Wt_15(i)])\
+	AS2(	mov ebx, AS_REG_7d	)\
+	AS2(	shr AS_REG_7d, 10		)\
+	AS2(	ror ebx, 17		)\
+	AS2(	xor AS_REG_7d, ebx	)\
+	AS2(	ror ebx, 2		)\
+	AS2(	xor ebx, AS_REG_7d	)/* s1(W_t-2) */\
+	AS2(	add ebx, [Wt_7(i)])\
+	AS2(	mov AS_REG_7d, edi	)\
+	AS2(	shr AS_REG_7d, 3		)\
+	AS2(	ror edi, 7		)\
+	AS2(	add ebx, [Wt(i)])/* s1(W_t-2) + W_t-7 + W_t-16 */\
+	AS2(	xor AS_REG_7d, edi	)\
+	AS2(	add edx, [Kt(i)])\
+	AS2(	ror edi, 11		)\
+	AS2(	add edx, H(i)	)\
+	AS2(	xor AS_REG_7d, edi	)/* s0(W_t-15) */\
+	AS2(	add AS_REG_7d, ebx	)/* W_t = s1(W_t-2) + W_t-7 + s0(W_t-15) W_t-16*/\
+	AS2(	mov [Wt(i)], AS_REG_7d)\
+	AS2(	add edx, AS_REG_7d	)\
+
+#define ROUND(i, r, eax, ecx, edi, edx)\
+	/* in: edi = E	*/\
+	/* unused: eax, ecx, temp: ebx, AS_REG_7d, out: edx = T1 */\
+	AS2(	mov edx, F(i)	)\
+	AS2(	xor edx, G(i)	)\
+	AS2(	and edx, edi	)\
+	AS2(	xor edx, G(i)	)/* Ch(E,F,G) = (G^(E&(F^G))) */\
+	AS2(	mov AS_REG_7d, edi	)\
+	AS2(	ror edi, 6		)\
+	AS2(	ror AS_REG_7d, 25		)\
+	RA##r(i, edx, edi		)/* H + Wt + Kt + Ch(E,F,G) */\
+	AS2(	xor AS_REG_7d, edi	)\
+	AS2(	ror edi, 5		)\
+	AS2(	xor AS_REG_7d, edi	)/* S1(E) */\
+	AS2(	add edx, AS_REG_7d	)/* T1 = S1(E) + Ch(E,F,G) + H + Wt + Kt */\
+	RB##r(i, edx, edi		)/* H + Wt + Kt + Ch(E,F,G) */\
+	/* in: ecx = A, eax = B^C, edx = T1 */\
+	/* unused: edx, temp: ebx, AS_REG_7d, out: eax = A, ecx = B^C, edx = E */\
+	AS2(	mov ebx, ecx	)\
+	AS2(	xor ecx, B(i)	)/* A^B */\
+	AS2(	and eax, ecx	)\
+	AS2(	xor eax, B(i)	)/* Maj(A,B,C) = B^((A^B)&(B^C) */\
+	AS2(	mov AS_REG_7d, ebx	)\
+	AS2(	ror ebx, 2		)\
+	AS2(	add eax, edx	)/* T1 + Maj(A,B,C) */\
+	AS2(	add edx, D(i)	)\
+	AS2(	mov D(i), edx	)\
+	AS2(	ror AS_REG_7d, 22		)\
+	AS2(	xor AS_REG_7d, ebx	)\
+	AS2(	ror ebx, 11		)\
+	AS2(	xor AS_REG_7d, ebx	)\
+	AS2(	add eax, AS_REG_7d	)/* T1 + S0(A) + Maj(A,B,C) */\
+	AS2(	mov H(i), eax	)\
+
+#define SWAP_COPY(i)		\
+	AS2(	mov		WORD_REG(bx), [WORD_REG(dx)+i*WORD_SZ])\
+	AS1(	bswap	WORD_REG(bx))\
+	AS2(	mov		[Wt(i*(1+CRYPTOPP_BOOL_X64)+CRYPTOPP_BOOL_X64)], WORD_REG(bx))
+
+#if defined(__GNUC__)
+	#if CRYPTOPP_BOOL_X64
+		FixedSizeAlignedSecBlock<byte, LOCALS_SIZE> workspace;
+	#endif
+	__asm__ __volatile__
+	(
+	#if CRYPTOPP_BOOL_X64
+		"lea %4, %%r8;"
+	#endif
+	".intel_syntax noprefix;"
+#elif defined(CRYPTOPP_GENERATE_X64_MASM)
+		ALIGN   8
+	X86_SHA256_HashBlocks	PROC FRAME
+		rex_push_reg rsi
+		push_reg rdi
+		push_reg rbx
+		push_reg rbp
+		alloc_stack(LOCALS_SIZE+8)
+		.endprolog
+		mov rdi, r8
+		lea rsi, [?SHA256_K@CryptoPP@@3QBIB + 48*4]
+#endif
+
+#if CRYPTOPP_BOOL_X86
+	#ifndef __GNUC__
+		AS2(	mov		edi, [len])
+		AS2(	lea		WORD_REG(si), [SHA256_K+48*4])
+	#endif
+	#if !defined(_MSC_VER) || (_MSC_VER < 1400)
+		AS_PUSH_IF86(bx)
+	#endif
+
+	AS_PUSH_IF86(bp)
+	AS2(	mov		ebx, esp)
+	AS2(	and		esp, -16)
+	AS2(	sub		WORD_REG(sp), LOCALS_SIZE)
+	AS_PUSH_IF86(bx)
+#endif
+	AS2(	mov		STATE_SAVE, WORD_REG(cx))
+	AS2(	mov		DATA_SAVE, WORD_REG(dx))
+	AS2(	add		WORD_REG(di), WORD_REG(dx))
+	AS2(	mov		DATA_END, WORD_REG(di))
+	AS2(	mov		K_END, WORD_REG(si))
+
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+#if CRYPTOPP_BOOL_X86
+	AS2(	test	edi, 1)
+	ASJ(	jnz,	2, f)
+#endif
+	AS2(	movdqa	xmm0, XMMWORD_PTR [WORD_REG(cx)+0*16])
+	AS2(	movdqa	xmm1, XMMWORD_PTR [WORD_REG(cx)+1*16])
+#endif
+
+#if CRYPTOPP_BOOL_X86
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+	ASJ(	jmp,	0, f)
+#endif
+	ASL(2)	// non-SSE2
+	AS2(	mov		esi, ecx)
+	AS2(	lea		edi, A(0))
+	AS2(	mov		ecx, 8)
+	AS1(	rep movsd)
+	AS2(	mov		esi, K_END)
+	ASJ(	jmp,	3, f)
+#endif
+
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+	ASL(0)
+	AS2(	movdqa	E(0), xmm1)
+	AS2(	movdqa	A(0), xmm0)
+#endif
+#if CRYPTOPP_BOOL_X86
+	ASL(3)
+#endif
+	AS2(	sub		WORD_REG(si), 48*4)
+	SWAP_COPY(0)	SWAP_COPY(1)	SWAP_COPY(2)	SWAP_COPY(3)
+	SWAP_COPY(4)	SWAP_COPY(5)	SWAP_COPY(6)	SWAP_COPY(7)
+#if CRYPTOPP_BOOL_X86
+	SWAP_COPY(8)	SWAP_COPY(9)	SWAP_COPY(10)	SWAP_COPY(11)
+	SWAP_COPY(12)	SWAP_COPY(13)	SWAP_COPY(14)	SWAP_COPY(15)
+#endif
+	AS2(	mov		edi, E(0))	// E
+	AS2(	mov		eax, B(0))	// B
+	AS2(	xor		eax, C(0))	// B^C
+	AS2(	mov		ecx, A(0))	// A
+
+	ROUND(0, 0, eax, ecx, edi, edx)
+	ROUND(1, 0, ecx, eax, edx, edi)
+	ROUND(2, 0, eax, ecx, edi, edx)
+	ROUND(3, 0, ecx, eax, edx, edi)
+	ROUND(4, 0, eax, ecx, edi, edx)
+	ROUND(5, 0, ecx, eax, edx, edi)
+	ROUND(6, 0, eax, ecx, edi, edx)
+	ROUND(7, 0, ecx, eax, edx, edi)
+	ROUND(8, 0, eax, ecx, edi, edx)
+	ROUND(9, 0, ecx, eax, edx, edi)
+	ROUND(10, 0, eax, ecx, edi, edx)
+	ROUND(11, 0, ecx, eax, edx, edi)
+	ROUND(12, 0, eax, ecx, edi, edx)
+	ROUND(13, 0, ecx, eax, edx, edi)
+	ROUND(14, 0, eax, ecx, edi, edx)
+	ROUND(15, 0, ecx, eax, edx, edi)
+
+	ASL(1)
+	AS2(add WORD_REG(si), 4*16)
+	ROUND(0, 1, eax, ecx, edi, edx)
+	ROUND(1, 1, ecx, eax, edx, edi)
+	ROUND(2, 1, eax, ecx, edi, edx)
+	ROUND(3, 1, ecx, eax, edx, edi)
+	ROUND(4, 1, eax, ecx, edi, edx)
+	ROUND(5, 1, ecx, eax, edx, edi)
+	ROUND(6, 1, eax, ecx, edi, edx)
+	ROUND(7, 1, ecx, eax, edx, edi)
+	ROUND(8, 1, eax, ecx, edi, edx)
+	ROUND(9, 1, ecx, eax, edx, edi)
+	ROUND(10, 1, eax, ecx, edi, edx)
+	ROUND(11, 1, ecx, eax, edx, edi)
+	ROUND(12, 1, eax, ecx, edi, edx)
+	ROUND(13, 1, ecx, eax, edx, edi)
+	ROUND(14, 1, eax, ecx, edi, edx)
+	ROUND(15, 1, ecx, eax, edx, edi)
+	AS2(	cmp		WORD_REG(si), K_END)
+	ASJ(	jne,	1, b)
+
+	AS2(	mov		WORD_REG(dx), DATA_SAVE)
+	AS2(	add		WORD_REG(dx), 64)
+	AS2(	mov		AS_REG_7, STATE_SAVE)
+	AS2(	mov		DATA_SAVE, WORD_REG(dx))
+
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+#if CRYPTOPP_BOOL_X86
+	AS2(	test	DWORD PTR DATA_END, 1)
+	ASJ(	jnz,	4, f)
+#endif
+	AS2(	movdqa	xmm1, XMMWORD_PTR [AS_REG_7+1*16])
+	AS2(	movdqa	xmm0, XMMWORD_PTR [AS_REG_7+0*16])
+	AS2(	paddd	xmm1, E(0))
+	AS2(	paddd	xmm0, A(0))
+	AS2(	movdqa	[AS_REG_7+1*16], xmm1)
+	AS2(	movdqa	[AS_REG_7+0*16], xmm0)
+	AS2(	cmp		WORD_REG(dx), DATA_END)
+	ASJ(	jl,		0, b)
+#endif
+
+#if CRYPTOPP_BOOL_X86
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+	ASJ(	jmp,	5, f)
+	ASL(4)	// non-SSE2
+#endif
+	AS2(	add		[AS_REG_7+0*4], ecx)	// A
+	AS2(	add		[AS_REG_7+4*4], edi)	// E
+	AS2(	mov		eax, B(0))
+	AS2(	mov		ebx, C(0))
+	AS2(	mov		ecx, D(0))
+	AS2(	add		[AS_REG_7+1*4], eax)
+	AS2(	add		[AS_REG_7+2*4], ebx)
+	AS2(	add		[AS_REG_7+3*4], ecx)
+	AS2(	mov		eax, F(0))
+	AS2(	mov		ebx, G(0))
+	AS2(	mov		ecx, H(0))
+	AS2(	add		[AS_REG_7+5*4], eax)
+	AS2(	add		[AS_REG_7+6*4], ebx)
+	AS2(	add		[AS_REG_7+7*4], ecx)
+	AS2(	mov		ecx, AS_REG_7d)
+	AS2(	cmp		WORD_REG(dx), DATA_END)
+	ASJ(	jl,		2, b)
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+	ASL(5)
+#endif
+#endif
+
+	AS_POP_IF86(sp)
+	AS_POP_IF86(bp)
+	#if !defined(_MSC_VER) || (_MSC_VER < 1400)
+		AS_POP_IF86(bx)
+	#endif
+
+#ifdef CRYPTOPP_GENERATE_X64_MASM
+	add		rsp, LOCALS_SIZE+8
+	pop		rbp
+	pop		rbx
+	pop		rdi
+	pop		rsi
+	ret
+	X86_SHA256_HashBlocks ENDP
+#endif
+
+#ifdef __GNUC__
+	".att_syntax prefix;"
+	: 
+	: "c" (state), "d" (data), "S" (SHA256_K+48), "D" (len)
+	#if CRYPTOPP_BOOL_X64
+		, "m" (workspace[0])
+	#endif
+	: "memory", "cc", "%eax"
+	#if CRYPTOPP_BOOL_X64
+		, "%rbx", "%r8"
+	#endif
+	);
+#endif
+}
+
+#endif	// #if defined(CRYPTOPP_X86_ASM_AVAILABLE) || defined(CRYPTOPP_GENERATE_X64_MASM)
+
+#ifndef CRYPTOPP_GENERATE_X64_MASM
+
+#ifdef CRYPTOPP_X64_MASM_AVAILABLE
+extern "C" {
+void CRYPTOPP_FASTCALL X86_SHA256_HashBlocks(word32 *state, const word32 *data, size_t len);
+}
+#endif
+
+#if defined(CRYPTOPP_X86_ASM_AVAILABLE) || defined(CRYPTOPP_X64_MASM_AVAILABLE)
+
+size_t SHA256::HashMultipleBlocks(const word32 *input, size_t length)
+{
+	X86_SHA256_HashBlocks(m_state, input, (length&(size_t(0)-BLOCKSIZE)) - !HasSSE2());
+	return length % BLOCKSIZE;
+}
+
+size_t SHA224::HashMultipleBlocks(const word32 *input, size_t length)
+{
+	X86_SHA256_HashBlocks(m_state, input, (length&(size_t(0)-BLOCKSIZE)) - !HasSSE2());
+	return length % BLOCKSIZE;
+}
+
+#endif
+
+#define blk2(i) (W[i&15]+=s1(W[(i-2)&15])+W[(i-7)&15]+s0(W[(i-15)&15]))
+
+#define Ch(x,y,z) (z^(x&(y^z)))
+#define Maj(x,y,z) (y^((x^y)&(y^z)))
+
+#define a(i) T[(0-i)&7]
+#define b(i) T[(1-i)&7]
+#define c(i) T[(2-i)&7]
+#define d(i) T[(3-i)&7]
+#define e(i) T[(4-i)&7]
+#define f(i) T[(5-i)&7]
+#define g(i) T[(6-i)&7]
+#define h(i) T[(7-i)&7]
+
+#define R(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+SHA256_K[i+j]+(j?blk2(i):blk0(i));\
+	d(i)+=h(i);h(i)+=S0(a(i))+Maj(a(i),b(i),c(i))
+
+// for SHA256
+#define S0(x) (rotrFixed(x,2)^rotrFixed(x,13)^rotrFixed(x,22))
+#define S1(x) (rotrFixed(x,6)^rotrFixed(x,11)^rotrFixed(x,25))
+#define s0(x) (rotrFixed(x,7)^rotrFixed(x,18)^(x>>3))
+#define s1(x) (rotrFixed(x,17)^rotrFixed(x,19)^(x>>10))
+
+void SHA256::Transform(word32 *state, const word32 *data)
+{
+	word32 W[16];
+#if defined(CRYPTOPP_X86_ASM_AVAILABLE) || defined(CRYPTOPP_X64_MASM_AVAILABLE)
+	// this byte reverse is a waste of time, but this function is only called by MDC
+	ByteReverse(W, data, BLOCKSIZE);
+	X86_SHA256_HashBlocks(state, W, BLOCKSIZE - !HasSSE2());
+#else
+	word32 T[8];
+    /* Copy context->state[] to working vars */
+	memcpy(T, state, sizeof(T));
+    /* 64 operations, partially loop unrolled */
+	for (unsigned int j=0; j<64; j+=16)
+	{
+		R( 0); R( 1); R( 2); R( 3);
+		R( 4); R( 5); R( 6); R( 7);
+		R( 8); R( 9); R(10); R(11);
+		R(12); R(13); R(14); R(15);
+	}
+    /* Add the working vars back into context.state[] */
+    state[0] += a(0);
+    state[1] += b(0);
+    state[2] += c(0);
+    state[3] += d(0);
+    state[4] += e(0);
+    state[5] += f(0);
+    state[6] += g(0);
+    state[7] += h(0);
+#endif
+}
+
+/* 
+// smaller but slower
+void SHA256::Transform(word32 *state, const word32 *data)
+{
+	word32 T[20];
+	word32 W[32];
+	unsigned int i = 0, j = 0;
+	word32 *t = T+8;
+
+	memcpy(t, state, 8*4);
+	word32 e = t[4], a = t[0];
+
+	do 
+	{
+		word32 w = data[j];
+		W[j] = w;
+		w += SHA256_K[j];
+		w += t[7];
+		w += S1(e);
+		w += Ch(e, t[5], t[6]);
+		e = t[3] + w;
+		t[3] = t[3+8] = e;
+		w += S0(t[0]);
+		a = w + Maj(a, t[1], t[2]);
+		t[-1] = t[7] = a;
+		--t;
+		++j;
+		if (j%8 == 0)
+			t += 8;
+	} while (j<16);
+
+	do
+	{
+		i = j&0xf;
+		word32 w = s1(W[i+16-2]) + s0(W[i+16-15]) + W[i] + W[i+16-7];
+		W[i+16] = W[i] = w;
+		w += SHA256_K[j];
+		w += t[7];
+		w += S1(e);
+		w += Ch(e, t[5], t[6]);
+		e = t[3] + w;
+		t[3] = t[3+8] = e;
+		w += S0(t[0]);
+		a = w + Maj(a, t[1], t[2]);
+		t[-1] = t[7] = a;
+
+		w = s1(W[(i+1)+16-2]) + s0(W[(i+1)+16-15]) + W[(i+1)] + W[(i+1)+16-7];
+		W[(i+1)+16] = W[(i+1)] = w;
+		w += SHA256_K[j+1];
+		w += (t-1)[7];
+		w += S1(e);
+		w += Ch(e, (t-1)[5], (t-1)[6]);
+		e = (t-1)[3] + w;
+		(t-1)[3] = (t-1)[3+8] = e;
+		w += S0((t-1)[0]);
+		a = w + Maj(a, (t-1)[1], (t-1)[2]);
+		(t-1)[-1] = (t-1)[7] = a;
+
+		t-=2;
+		j+=2;
+		if (j%8 == 0)
+			t += 8;
+	} while (j<64);
+
+    state[0] += a;
+    state[1] += t[1];
+    state[2] += t[2];
+    state[3] += t[3];
+    state[4] += e;
+    state[5] += t[5];
+    state[6] += t[6];
+    state[7] += t[7];
+}
+*/
+
+#undef S0
+#undef S1
+#undef s0
+#undef s1
+#undef R
+
+// *************************************************************
+
+void SHA384::InitState(HashWordType *state)
+{
+	static const word64 s[8] = {
+		W64LIT(0xcbbb9d5dc1059ed8), W64LIT(0x629a292a367cd507),
+		W64LIT(0x9159015a3070dd17), W64LIT(0x152fecd8f70e5939),
+		W64LIT(0x67332667ffc00b31), W64LIT(0x8eb44a8768581511),
+		W64LIT(0xdb0c2e0d64f98fa7), W64LIT(0x47b5481dbefa4fa4)};
+	memcpy(state, s, sizeof(s));
+}
+
+void SHA512::InitState(HashWordType *state)
+{
+	static const word64 s[8] = {
+		W64LIT(0x6a09e667f3bcc908), W64LIT(0xbb67ae8584caa73b),
+		W64LIT(0x3c6ef372fe94f82b), W64LIT(0xa54ff53a5f1d36f1),
+		W64LIT(0x510e527fade682d1), W64LIT(0x9b05688c2b3e6c1f),
+		W64LIT(0x1f83d9abfb41bd6b), W64LIT(0x5be0cd19137e2179)};
+	memcpy(state, s, sizeof(s));
+}
+
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && CRYPTOPP_BOOL_X86
+CRYPTOPP_ALIGN_DATA(16) static const word64 SHA512_K[80] CRYPTOPP_SECTION_ALIGN16 = {
+#else
+static const word64 SHA512_K[80] = {
+#endif
+	W64LIT(0x428a2f98d728ae22), W64LIT(0x7137449123ef65cd),
+	W64LIT(0xb5c0fbcfec4d3b2f), W64LIT(0xe9b5dba58189dbbc),
+	W64LIT(0x3956c25bf348b538), W64LIT(0x59f111f1b605d019),
+	W64LIT(0x923f82a4af194f9b), W64LIT(0xab1c5ed5da6d8118),
+	W64LIT(0xd807aa98a3030242), W64LIT(0x12835b0145706fbe),
+	W64LIT(0x243185be4ee4b28c), W64LIT(0x550c7dc3d5ffb4e2),
+	W64LIT(0x72be5d74f27b896f), W64LIT(0x80deb1fe3b1696b1),
+	W64LIT(0x9bdc06a725c71235), W64LIT(0xc19bf174cf692694),
+	W64LIT(0xe49b69c19ef14ad2), W64LIT(0xefbe4786384f25e3),
+	W64LIT(0x0fc19dc68b8cd5b5), W64LIT(0x240ca1cc77ac9c65),
+	W64LIT(0x2de92c6f592b0275), W64LIT(0x4a7484aa6ea6e483),
+	W64LIT(0x5cb0a9dcbd41fbd4), W64LIT(0x76f988da831153b5),
+	W64LIT(0x983e5152ee66dfab), W64LIT(0xa831c66d2db43210),
+	W64LIT(0xb00327c898fb213f), W64LIT(0xbf597fc7beef0ee4),
+	W64LIT(0xc6e00bf33da88fc2), W64LIT(0xd5a79147930aa725),
+	W64LIT(0x06ca6351e003826f), W64LIT(0x142929670a0e6e70),
+	W64LIT(0x27b70a8546d22ffc), W64LIT(0x2e1b21385c26c926),
+	W64LIT(0x4d2c6dfc5ac42aed), W64LIT(0x53380d139d95b3df),
+	W64LIT(0x650a73548baf63de), W64LIT(0x766a0abb3c77b2a8),
+	W64LIT(0x81c2c92e47edaee6), W64LIT(0x92722c851482353b),
+	W64LIT(0xa2bfe8a14cf10364), W64LIT(0xa81a664bbc423001),
+	W64LIT(0xc24b8b70d0f89791), W64LIT(0xc76c51a30654be30),
+	W64LIT(0xd192e819d6ef5218), W64LIT(0xd69906245565a910),
+	W64LIT(0xf40e35855771202a), W64LIT(0x106aa07032bbd1b8),
+	W64LIT(0x19a4c116b8d2d0c8), W64LIT(0x1e376c085141ab53),
+	W64LIT(0x2748774cdf8eeb99), W64LIT(0x34b0bcb5e19b48a8),
+	W64LIT(0x391c0cb3c5c95a63), W64LIT(0x4ed8aa4ae3418acb),
+	W64LIT(0x5b9cca4f7763e373), W64LIT(0x682e6ff3d6b2b8a3),
+	W64LIT(0x748f82ee5defb2fc), W64LIT(0x78a5636f43172f60),
+	W64LIT(0x84c87814a1f0ab72), W64LIT(0x8cc702081a6439ec),
+	W64LIT(0x90befffa23631e28), W64LIT(0xa4506cebde82bde9),
+	W64LIT(0xbef9a3f7b2c67915), W64LIT(0xc67178f2e372532b),
+	W64LIT(0xca273eceea26619c), W64LIT(0xd186b8c721c0c207),
+	W64LIT(0xeada7dd6cde0eb1e), W64LIT(0xf57d4f7fee6ed178),
+	W64LIT(0x06f067aa72176fba), W64LIT(0x0a637dc5a2c898a6),
+	W64LIT(0x113f9804bef90dae), W64LIT(0x1b710b35131c471b),
+	W64LIT(0x28db77f523047d84), W64LIT(0x32caab7b40c72493),
+	W64LIT(0x3c9ebe0a15c9bebc), W64LIT(0x431d67c49c100d4c),
+	W64LIT(0x4cc5d4becb3e42b6), W64LIT(0x597f299cfc657e2a),
+	W64LIT(0x5fcb6fab3ad6faec), W64LIT(0x6c44198c4a475817)
+};
+
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && CRYPTOPP_BOOL_X86
+// put assembly version in separate function, otherwise MSVC 2005 SP1 doesn't generate correct code for the non-assembly version
+CRYPTOPP_NAKED static void CRYPTOPP_FASTCALL SHA512_SSE2_Transform(word64 *state, const word64 *data)
+{
+#ifdef __GNUC__
+	__asm__ __volatile__
+	(
+		".intel_syntax noprefix;"
+	AS1(	push	ebx)
+	AS2(	mov		ebx, eax)
+#else
+	AS1(	push	ebx)
+	AS1(	push	esi)
+	AS1(	push	edi)
+	AS2(	lea		ebx, SHA512_K)
+#endif
+
+	AS2(	mov		eax, esp)
+	AS2(	and		esp, 0xfffffff0)
+	AS2(	sub		esp, 27*16)				// 17*16 for expanded data, 20*8 for state
+	AS1(	push	eax)
+	AS2(	xor		eax, eax)
+	AS2(	lea		edi, [esp+4+8*8])		// start at middle of state buffer. will decrement pointer each round to avoid copying
+	AS2(	lea		esi, [esp+4+20*8+8])	// 16-byte alignment, then add 8
+
+	AS2(	movdqa	xmm0, [ecx+0*16])
+	AS2(	movdq2q	mm4, xmm0)
+	AS2(	movdqa	[edi+0*16], xmm0)
+	AS2(	movdqa	xmm0, [ecx+1*16])
+	AS2(	movdqa	[edi+1*16], xmm0)
+	AS2(	movdqa	xmm0, [ecx+2*16])
+	AS2(	movdq2q	mm5, xmm0)
+	AS2(	movdqa	[edi+2*16], xmm0)
+	AS2(	movdqa	xmm0, [ecx+3*16])
+	AS2(	movdqa	[edi+3*16], xmm0)
+	ASJ(	jmp,	0, f)
+
+#define SSE2_S0_S1(r, a, b, c)	\
+	AS2(	movq	mm6, r)\
+	AS2(	psrlq	r, a)\
+	AS2(	movq	mm7, r)\
+	AS2(	psllq	mm6, 64-c)\
+	AS2(	pxor	mm7, mm6)\
+	AS2(	psrlq	r, b-a)\
+	AS2(	pxor	mm7, r)\
+	AS2(	psllq	mm6, c-b)\
+	AS2(	pxor	mm7, mm6)\
+	AS2(	psrlq	r, c-b)\
+	AS2(	pxor	r, mm7)\
+	AS2(	psllq	mm6, b-a)\
+	AS2(	pxor	r, mm6)
+
+#define SSE2_s0(r, a, b, c)	\
+	AS2(	movdqa	xmm6, r)\
+	AS2(	psrlq	r, a)\
+	AS2(	movdqa	xmm7, r)\
+	AS2(	psllq	xmm6, 64-c)\
+	AS2(	pxor	xmm7, xmm6)\
+	AS2(	psrlq	r, b-a)\
+	AS2(	pxor	xmm7, r)\
+	AS2(	psrlq	r, c-b)\
+	AS2(	pxor	r, xmm7)\
+	AS2(	psllq	xmm6, c-a)\
+	AS2(	pxor	r, xmm6)
+
+#define SSE2_s1(r, a, b, c)	\
+	AS2(	movdqa	xmm6, r)\
+	AS2(	psrlq	r, a)\
+	AS2(	movdqa	xmm7, r)\
+	AS2(	psllq	xmm6, 64-c)\
+	AS2(	pxor	xmm7, xmm6)\
+	AS2(	psrlq	r, b-a)\
+	AS2(	pxor	xmm7, r)\
+	AS2(	psllq	xmm6, c-b)\
+	AS2(	pxor	xmm7, xmm6)\
+	AS2(	psrlq	r, c-b)\
+	AS2(	pxor	r, xmm7)
+
+	ASL(SHA512_Round)
+	// k + w is in mm0, a is in mm4, e is in mm5
+	AS2(	paddq	mm0, [edi+7*8])		// h
+	AS2(	movq	mm2, [edi+5*8])		// f
+	AS2(	movq	mm3, [edi+6*8])		// g
+	AS2(	pxor	mm2, mm3)
+	AS2(	pand	mm2, mm5)
+	SSE2_S0_S1(mm5,14,18,41)
+	AS2(	pxor	mm2, mm3)
+	AS2(	paddq	mm0, mm2)			// h += Ch(e,f,g)
+	AS2(	paddq	mm5, mm0)			// h += S1(e)
+	AS2(	movq	mm2, [edi+1*8])		// b
+	AS2(	movq	mm1, mm2)
+	AS2(	por		mm2, mm4)
+	AS2(	pand	mm2, [edi+2*8])		// c
+	AS2(	pand	mm1, mm4)
+	AS2(	por		mm1, mm2)
+	AS2(	paddq	mm1, mm5)			// temp = h + Maj(a,b,c)
+	AS2(	paddq	mm5, [edi+3*8])		// e = d + h
+	AS2(	movq	[edi+3*8], mm5)
+	AS2(	movq	[edi+11*8], mm5)
+	SSE2_S0_S1(mm4,28,34,39)			// S0(a)
+	AS2(	paddq	mm4, mm1)			// a = temp + S0(a)
+	AS2(	movq	[edi-8], mm4)
+	AS2(	movq	[edi+7*8], mm4)
+	AS1(	ret)
+
+	// first 16 rounds
+	ASL(0)
+	AS2(	movq	mm0, [edx+eax*8])
+	AS2(	movq	[esi+eax*8], mm0)
+	AS2(	movq	[esi+eax*8+16*8], mm0)
+	AS2(	paddq	mm0, [ebx+eax*8])
+	ASC(	call,	SHA512_Round)
+	AS1(	inc		eax)
+	AS2(	sub		edi, 8)
+	AS2(	test	eax, 7)
+	ASJ(	jnz,	0, b)
+	AS2(	add		edi, 8*8)
+	AS2(	cmp		eax, 16)
+	ASJ(	jne,	0, b)
+
+	// rest of the rounds
+	AS2(	movdqu	xmm0, [esi+(16-2)*8])
+	ASL(1)
+	// data expansion, W[i-2] already in xmm0
+	AS2(	movdqu	xmm3, [esi])
+	AS2(	paddq	xmm3, [esi+(16-7)*8])
+	AS2(	movdqa	xmm2, [esi+(16-15)*8])
+	SSE2_s1(xmm0, 6, 19, 61)
+	AS2(	paddq	xmm0, xmm3)
+	SSE2_s0(xmm2, 1, 7, 8)
+	AS2(	paddq	xmm0, xmm2)
+	AS2(	movdq2q	mm0, xmm0)
+	AS2(	movhlps	xmm1, xmm0)
+	AS2(	paddq	mm0, [ebx+eax*8])
+	AS2(	movlps	[esi], xmm0)
+	AS2(	movlps	[esi+8], xmm1)
+	AS2(	movlps	[esi+8*16], xmm0)
+	AS2(	movlps	[esi+8*17], xmm1)
+	// 2 rounds
+	ASC(	call,	SHA512_Round)
+	AS2(	sub		edi, 8)
+	AS2(	movdq2q	mm0, xmm1)
+	AS2(	paddq	mm0, [ebx+eax*8+8])
+	ASC(	call,	SHA512_Round)
+	// update indices and loop
+	AS2(	add		esi, 16)
+	AS2(	add		eax, 2)
+	AS2(	sub		edi, 8)
+	AS2(	test	eax, 7)
+	ASJ(	jnz,	1, b)
+	// do housekeeping every 8 rounds
+	AS2(	mov		esi, 0xf)
+	AS2(	and		esi, eax)
+	AS2(	lea		esi, [esp+4+20*8+8+esi*8])
+	AS2(	add		edi, 8*8)
+	AS2(	cmp		eax, 80)
+	ASJ(	jne,	1, b)
+
+#define SSE2_CombineState(i)	\
+	AS2(	movdqa	xmm0, [edi+i*16])\
+	AS2(	paddq	xmm0, [ecx+i*16])\
+	AS2(	movdqa	[ecx+i*16], xmm0)
+
+	SSE2_CombineState(0)
+	SSE2_CombineState(1)
+	SSE2_CombineState(2)
+	SSE2_CombineState(3)
+
+	AS1(	pop		esp)
+	AS1(	emms)
+
+#if defined(__GNUC__)
+	AS1(	pop		ebx)
+	".att_syntax prefix;"
+		:
+		: "a" (SHA512_K), "c" (state), "d" (data)
+		: "%esi", "%edi", "memory", "cc"
+	);
+#else
+	AS1(	pop		edi)
+	AS1(	pop		esi)
+	AS1(	pop		ebx)
+	AS1(	ret)
+#endif
+}
+#endif	// #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+
+void SHA512::Transform(word64 *state, const word64 *data)
+{
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && CRYPTOPP_BOOL_X86
+	if (HasSSE2())
+	{
+		SHA512_SSE2_Transform(state, data);
+		return;
+	}
+#endif
+
+#define S0(x) (rotrFixed(x,28)^rotrFixed(x,34)^rotrFixed(x,39))
+#define S1(x) (rotrFixed(x,14)^rotrFixed(x,18)^rotrFixed(x,41))
+#define s0(x) (rotrFixed(x,1)^rotrFixed(x,8)^(x>>7))
+#define s1(x) (rotrFixed(x,19)^rotrFixed(x,61)^(x>>6))
+
+#define R(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+SHA512_K[i+j]+(j?blk2(i):blk0(i));\
+	d(i)+=h(i);h(i)+=S0(a(i))+Maj(a(i),b(i),c(i))
+
+	word64 W[16];
+	word64 T[8];
+    /* Copy context->state[] to working vars */
+	memcpy(T, state, sizeof(T));
+    /* 80 operations, partially loop unrolled */
+	for (unsigned int j=0; j<80; j+=16)
+	{
+		R( 0); R( 1); R( 2); R( 3);
+		R( 4); R( 5); R( 6); R( 7);
+		R( 8); R( 9); R(10); R(11);
+		R(12); R(13); R(14); R(15);
+	}
+    /* Add the working vars back into context.state[] */
+    state[0] += a(0);
+    state[1] += b(0);
+    state[2] += c(0);
+    state[3] += d(0);
+    state[4] += e(0);
+    state[5] += f(0);
+    state[6] += g(0);
+    state[7] += h(0);
+}
+
+NAMESPACE_END
+
+#endif	// #ifndef CRYPTOPP_GENERATE_X64_MASM
+#endif	// #ifndef CRYPTOPP_IMPORTS
new file mode 100644
--- /dev/null
+++ b/cryptopp/sha.h
@@ -0,0 +1,63 @@
+#ifndef CRYPTOPP_SHA_H
+#define CRYPTOPP_SHA_H
+
+#include "iterhash.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+/// <a href="http://www.weidai.com/scan-mirror/md.html#SHA-1">SHA-1</a>
+class CRYPTOPP_DLL SHA1 : public IteratedHashWithStaticTransform<word32, BigEndian, 64, 20, SHA1>
+{
+public:
+	static void CRYPTOPP_API InitState(HashWordType *state);
+	static void CRYPTOPP_API Transform(word32 *digest, const word32 *data);
+	static const char * CRYPTOPP_API StaticAlgorithmName() {return "SHA-1";}
+};
+
+typedef SHA1 SHA;	// for backwards compatibility
+
+//! implements the SHA-256 standard
+class CRYPTOPP_DLL SHA256 : public IteratedHashWithStaticTransform<word32, BigEndian, 64, 32, SHA256, 32, true>
+{
+public:
+#if defined(CRYPTOPP_X86_ASM_AVAILABLE) || defined(CRYPTOPP_X64_MASM_AVAILABLE)
+	size_t HashMultipleBlocks(const word32 *input, size_t length);
+#endif
+	static void CRYPTOPP_API InitState(HashWordType *state);
+	static void CRYPTOPP_API Transform(word32 *digest, const word32 *data);
+	static const char * CRYPTOPP_API StaticAlgorithmName() {return "SHA-256";}
+};
+
+//! implements the SHA-224 standard
+class CRYPTOPP_DLL SHA224 : public IteratedHashWithStaticTransform<word32, BigEndian, 64, 32, SHA224, 28, true>
+{
+public:
+#if defined(CRYPTOPP_X86_ASM_AVAILABLE) || defined(CRYPTOPP_X64_MASM_AVAILABLE)
+	size_t HashMultipleBlocks(const word32 *input, size_t length);
+#endif
+	static void CRYPTOPP_API InitState(HashWordType *state);
+	static void CRYPTOPP_API Transform(word32 *digest, const word32 *data) {SHA256::Transform(digest, data);}
+	static const char * CRYPTOPP_API StaticAlgorithmName() {return "SHA-224";}
+};
+
+//! implements the SHA-512 standard
+class CRYPTOPP_DLL SHA512 : public IteratedHashWithStaticTransform<word64, BigEndian, 128, 64, SHA512, 64, CRYPTOPP_BOOL_X86>
+{
+public:
+	static void CRYPTOPP_API InitState(HashWordType *state);
+	static void CRYPTOPP_API Transform(word64 *digest, const word64 *data);
+	static const char * CRYPTOPP_API StaticAlgorithmName() {return "SHA-512";}
+};
+
+//! implements the SHA-384 standard
+class CRYPTOPP_DLL SHA384 : public IteratedHashWithStaticTransform<word64, BigEndian, 128, 64, SHA384, 48, CRYPTOPP_BOOL_X86>
+{
+public:
+	static void CRYPTOPP_API InitState(HashWordType *state);
+	static void CRYPTOPP_API Transform(word64 *digest, const word64 *data) {SHA512::Transform(digest, data);}
+	static const char * CRYPTOPP_API StaticAlgorithmName() {return "SHA-384";}
+};
+
+NAMESPACE_END
+
+#endif
new file mode 100644
--- /dev/null
+++ b/cryptopp/simple.h
@@ -0,0 +1,1 @@
+
new file mode 100644
--- /dev/null
+++ b/cryptopp/smartptr.h
@@ -0,0 +1,223 @@
+#ifndef CRYPTOPP_SMARTPTR_H
+#define CRYPTOPP_SMARTPTR_H
+
+#include "config.h"
+#include <algorithm>
+
+NAMESPACE_BEGIN(CryptoPP)
+
+template <class T> class simple_ptr
+{
+public:
+	simple_ptr() : m_p(NULL) {}
+	~simple_ptr() {delete m_p;}
+	T *m_p;
+};
+
+template <class T> class member_ptr
+{
+public:
+	explicit member_ptr(T *p = NULL) : m_p(p) {}
+
+	~member_ptr();
+
+	const T& operator*() const { return *m_p; }
+	T& operator*() { return *m_p; }
+
+	const T* operator->() const { return m_p; }
+	T* operator->() { return m_p; }
+
+	const T* get() const { return m_p; }
+	T* get() { return m_p; }
+
+	T* release()
+	{
+		T *old_p = m_p;
+		m_p = 0;
+		return old_p;
+	} 
+
+	void reset(T *p = 0);
+
+protected:
+	member_ptr(const member_ptr<T>& rhs);		// copy not allowed
+	void operator=(const member_ptr<T>& rhs);	// assignment not allowed
+
+	T *m_p;
+};
+
+template <class T> member_ptr<T>::~member_ptr() {delete m_p;}
+template <class T> void member_ptr<T>::reset(T *p) {delete m_p; m_p = p;}
+
+// ********************************************************
+
+template<class T> class value_ptr : public member_ptr<T>
+{
+public:
+	value_ptr(const T &obj) : member_ptr<T>(new T(obj)) {}
+	value_ptr(T *p = NULL) : member_ptr<T>(p) {}
+	value_ptr(const value_ptr<T>& rhs)
+		: member_ptr<T>(rhs.m_p ? new T(*rhs.m_p) : NULL) {}
+
+	value_ptr<T>& operator=(const value_ptr<T>& rhs);
+	bool operator==(const value_ptr<T>& rhs)
+	{
+		return (!this->m_p && !rhs.m_p) || (this->m_p && rhs.m_p && *this->m_p == *rhs.m_p);
+	}
+};
+
+template <class T> value_ptr<T>& value_ptr<T>::operator=(const value_ptr<T>& rhs)
+{
+	T *old_p = this->m_p;
+	this->m_p = rhs.m_p ? new T(*rhs.m_p) : NULL;
+	delete old_p;
+	return *this;
+}
+
+// ********************************************************
+
+template<class T> class clonable_ptr : public member_ptr<T>
+{
+public:
+	clonable_ptr(const T &obj) : member_ptr<T>(obj.Clone()) {}
+	clonable_ptr(T *p = NULL) : member_ptr<T>(p) {}
+	clonable_ptr(const clonable_ptr<T>& rhs)
+		: member_ptr<T>(rhs.m_p ? rhs.m_p->Clone() : NULL) {}
+
+	clonable_ptr<T>& operator=(const clonable_ptr<T>& rhs);
+};
+
+template <class T> clonable_ptr<T>& clonable_ptr<T>::operator=(const clonable_ptr<T>& rhs)
+{
+	T *old_p = this->m_p;
+	this->m_p = rhs.m_p ? rhs.m_p->Clone() : NULL;
+	delete old_p;
+	return *this;
+}
+
+// ********************************************************
+
+template<class T> class counted_ptr
+{
+public:
+	explicit counted_ptr(T *p = 0);
+	counted_ptr(const T &r) : m_p(0) {attach(r);}
+	counted_ptr(const counted_ptr<T>& rhs);
+
+	~counted_ptr();
+
+	const T& operator*() const { return *m_p; }
+	T& operator*() { return *m_p; }
+
+	const T* operator->() const { return m_p; }
+	T* operator->() { return get(); }
+
+	const T* get() const { return m_p; }
+	T* get();
+
+	void attach(const T &p);
+
+	counted_ptr<T> & operator=(const counted_ptr<T>& rhs);
+
+private:
+	T *m_p;
+};
+
+template <class T> counted_ptr<T>::counted_ptr(T *p)
+	: m_p(p) 
+{
+	if (m_p)
+		m_p->m_referenceCount = 1;
+}
+
+template <class T> counted_ptr<T>::counted_ptr(const counted_ptr<T>& rhs)
+	: m_p(rhs.m_p)
+{
+	if (m_p)
+		m_p->m_referenceCount++;
+}
+
+template <class T> counted_ptr<T>::~counted_ptr()
+{
+	if (m_p && --m_p->m_referenceCount == 0)
+		delete m_p;
+}
+
+template <class T> void counted_ptr<T>::attach(const T &r)
+{
+	if (m_p && --m_p->m_referenceCount == 0)
+		delete m_p;
+	if (r.m_referenceCount == 0)
+	{
+		m_p = r.clone();
+		m_p->m_referenceCount = 1;
+	}
+	else
+	{
+		m_p = const_cast<T *>(&r);
+		m_p->m_referenceCount++;
+	}
+}
+
+template <class T> T* counted_ptr<T>::get()
+{
+	if (m_p && m_p->m_referenceCount > 1)
+	{
+		T *temp = m_p->clone();
+		m_p->m_referenceCount--;
+		m_p = temp;
+		m_p->m_referenceCount = 1;
+	}
+	return m_p;
+}
+
+template <class T> counted_ptr<T> & counted_ptr<T>::operator=(const counted_ptr<T>& rhs)
+{
+	if (m_p != rhs.m_p)
+	{
+		if (m_p && --m_p->m_referenceCount == 0)
+			delete m_p;
+		m_p = rhs.m_p;
+		if (m_p)
+			m_p->m_referenceCount++;
+	}
+	return *this;
+}
+
+// ********************************************************
+
+template <class T> class vector_member_ptrs
+{
+public:
+	vector_member_ptrs(size_t size=0)
+		: m_size(size), m_ptr(new member_ptr<T>[size]) {}
+	~vector_member_ptrs()
+		{delete [] this->m_ptr;}
+
+	member_ptr<T>& operator[](size_t index)
+		{assert(index<this->m_size); return this->m_ptr[index];}
+	const member_ptr<T>& operator[](size_t index) const
+		{assert(index<this->m_size); return this->m_ptr[index];}
+
+	size_t size() const {return this->m_size;}
+	void resize(size_t newSize)
+	{
+		member_ptr<T> *newPtr = new member_ptr<T>[newSize];
+		for (size_t i=0; i<this->m_size && i<newSize; i++)
+			newPtr[i].reset(this->m_ptr[i].release());
+		delete [] this->m_ptr;
+		this->m_size = newSize;
+		this->m_ptr = newPtr;
+	}
+
+private:
+	vector_member_ptrs(const vector_member_ptrs<T> &c);	// copy not allowed
+	void operator=(const vector_member_ptrs<T> &x);		// assignment not allowed
+
+	size_t m_size;
+	member_ptr<T> *m_ptr;
+};
+
+NAMESPACE_END
+
+#endif
new file mode 100644
--- /dev/null
+++ b/cryptopp/stdcpp.h
@@ -0,0 +1,27 @@
+#ifndef CRYPTOPP_STDCPP_H
+#define CRYPTOPP_STDCPP_H
+
+#include <stddef.h>
+#include <assert.h>
+#include <limits.h>
+#include <memory>
+#include <string>
+#include <exception>
+#include <typeinfo>
+
+
+#ifdef _MSC_VER
+#include <string.h>	// CodeWarrior doesn't have memory.h
+#include <algorithm>
+#include <map>
+#include <vector>
+
+// re-disable this
+#pragma warning(disable: 4231)
+#endif
+
+#if defined(_MSC_VER) && defined(_CRTAPI1)
+#define CRYPTOPP_MSVCRT6
+#endif
+
+#endif
--- a/main.cpp
+++ b/main.cpp
@@ -3,7 +3,7 @@
 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
 
 #include "headers.h"
-#include "sha.h"
+#include "cryptopp/sha.h"
 
 
 
@@ -1369,6 +1369,8 @@
         return error("AcceptBlock() : rejected by checkpoint lockin at 33333");
     if (pindexPrev->nHeight+1 == 68555 && hash != uint256("0x00000000001e1b4903550a0b96e9a9405c8a95f387162e4944e8d9fbe501cd6a"))
         return error("AcceptBlock() : rejected by checkpoint lockin at 68555");
+    if (pindexPrev->nHeight+1 == 70567 && hash != uint256("0x00000000006a49b14bcf27462068f1264c961f11fa2e0eddd2be0791e1d4124a"))
+        return error("AcceptBlock() : rejected by checkpoint lockin at 70567");
 
     // Write block to history file
     if (!CheckDiskSpace(::GetSerializeSize(*this, SER_DISK)))
@@ -2551,82 +2553,11 @@
 static const unsigned int pSHA256InitState[8] =
 {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};
 
-static const unsigned int SHA256_K[64] = {
-    0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
-    0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
-    0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
-    0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
-    0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
-    0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
-    0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
-    0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
-    0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
-    0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
-    0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
-    0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
-    0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
-    0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
-    0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
-    0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
-};
-
-#define blk0(i) (W[i] = dat[i])
-
-#define blk2(i) (W[i&15]+=s1(W[(i-2)&15])+W[(i-7)&15]+s0(W[(i-15)&15]))
-
-#define Ch(x,y,z) (z^(x&(y^z)))
-#define Maj(x,y,z) ((x&y)|(z&(x|y)))
-
-#define a(i) T[(0-i)&7]
-#define b(i) T[(1-i)&7]
-#define c(i) T[(2-i)&7]
-#define d(i) T[(3-i)&7]
-#define e(i) T[(4-i)&7]
-#define f(i) T[(5-i)&7]
-#define g(i) T[(6-i)&7]
-#define h(i) T[(7-i)&7]
-
-#define R(i,j) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+SHA256_K[i+j]+(j?blk2(i):blk0(i));\
-                                         d(i)+=h(i);h(i)+=S0(a(i))+Maj(a(i),b(i),c(i))
-
-#define rotrFixed(x,y) ((x>>y) | (x<<(sizeof(unsigned int)*8-y)))
-
-// for SHA256
-#define S0(x) (rotrFixed(x,2)^rotrFixed(x,13)^rotrFixed(x,22))
-#define S1(x) (rotrFixed(x,6)^rotrFixed(x,11)^rotrFixed(x,25))
-#define s0(x) (rotrFixed(x,7)^rotrFixed(x,18)^(x>>3))
-#define s1(x) (rotrFixed(x,17)^rotrFixed(x,19)^(x>>10))
-
-#if 1
-inline void SHA256Transform(void* pout, const void* pin, const void* pinit)
-{
-    memcpy(pout, pinit, 32);
-    unsigned int* dat = (unsigned int*)pin;
-    unsigned int* T = (unsigned int*)pout;
-    unsigned int* initstate = (unsigned int*)pinit;
-    unsigned int W[16];
-
-    R( 0,  0); R( 1,  0); R( 2,  0); R( 3,  0); R( 4,  0); R( 5,  0); R( 6,  0); R( 7,  0); R( 8,  0); R( 9,  0); R(10,  0); R(11,  0); R(12,  0); R(13,  0); R(14,  0); R(15,  0);
-    R( 0, 16); R( 1, 16); R( 2, 16); R( 3, 16); R( 4, 16); R( 5, 16); R( 6, 16); R( 7, 16); R( 8, 16); R( 9, 16); R(10, 16); R(11, 16); R(12, 16); R(13, 16); R(14, 16); R(15, 16);
-    R( 0, 32); R( 1, 32); R( 2, 32); R( 3, 32); R( 4, 32); R( 5, 32); R( 6, 32); R( 7, 32); R( 8, 32); R( 9, 32); R(10, 32); R(11, 32); R(12, 32); R(13, 32); R(14, 32); R(15, 32);
-    R( 0, 48); R( 1, 48); R( 2, 48); R( 3, 48); R( 4, 48); R( 5, 48); R( 6, 48); R( 7, 48); R( 8, 48); R( 9, 48); R(10, 48); R(11, 48); R(12, 48); R(13, 48); R(14, 48); R(15, 48);
-
-    T[0] += initstate[0];
-    T[1] += initstate[1];
-    T[2] += initstate[2];
-    T[3] += initstate[3];
-    T[4] += initstate[4];
-    T[5] += initstate[5];
-    T[6] += initstate[6];
-    T[7] += initstate[7];
-}
-#else
 inline void SHA256Transform(void* pstate, void* pinput, const void* pinit)
 {
     memcpy(pstate, pinit, 32);
     CryptoPP::SHA256::Transform((CryptoPP::word32*)pstate, (CryptoPP::word32*)pinput);
 }
-#endif
 
 
 
@@ -2645,7 +2576,7 @@
         Sleep(50);
         if (fShutdown)
             return;
-        while (vNodes.empty())
+        while (vNodes.empty() || IsInitialBlockDownload())
         {
             Sleep(1000);
             if (fShutdown)
@@ -2728,7 +2659,7 @@
         //
         // Prebuild hash buffer
         //
-        struct unnamed1
+        struct tmpworkspace
         {
             struct unnamed2
             {
@@ -2743,8 +2674,9 @@
             unsigned char pchPadding0[64];
             uint256 hash1;
             unsigned char pchPadding1[64];
-        }
-        tmp;
+        };
+        char tmpbuf[sizeof(tmpworkspace)+16];
+        tmpworkspace& tmp = *(tmpworkspace*)alignup<16>(tmpbuf);
 
         tmp.block.nVersion       = pblock->nVersion;
         tmp.block.hashPrevBlock  = pblock->hashPrevBlock  = (pindexPrev ? pindexPrev->GetBlockHash() : 0);
@@ -2761,7 +2693,8 @@
             ((unsigned int*)&tmp)[i] = ByteReverse(((unsigned int*)&tmp)[i]);
 
         // Precalc the first half of the first hash, which stays constant
-        uint256 midstate;
+        uint256 midstatebuf[2];
+        uint256& midstate = *alignup<16>(midstatebuf);
         SHA256Transform(&midstate, &tmp.block, pSHA256InitState);
 
 
@@ -2770,7 +2703,8 @@
         //
         int64 nStart = GetTime();
         uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
-        uint256 hash;
+        uint256 hashbuf[2];
+        uint256& hash = *alignup<16>(hashbuf);
         loop
         {
             SHA256Transform(&tmp.hash1, (char*)&tmp.block + 64, &midstate);
@@ -2868,25 +2802,7 @@
                 if (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60)
                     break;
                 if (pindexPrev != pindexBest)
-                {
-                    // Pause generating during initial download
-                    if (GetTime() - nStart < 20)
-                    {
-                        CBlockIndex* pindexTmp;
-                        do
-                        {
-                            pindexTmp = pindexBest;
-                            for (int i = 0; i < 10; i++)
-                            {
-                                Sleep(1000);
-                                if (fShutdown)
-                                    return;
-                            }
-                        }
-                        while (pindexTmp != pindexBest);
-                    }
                     break;
-                }
 
                 pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
                 tmp.block.nTime = ByteReverse(pblock->nTime);
--- a/makefile.mingw
+++ b/makefile.mingw
@@ -32,20 +32,7 @@
 DEBUGFLAGS=-g -D__WXDEBUG__
 CFLAGS=-mthreads -O2 -w -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
 HEADERS=headers.h strlcpy.h serialize.h uint256.h util.h key.h bignum.h base58.h \
-    script.h db.h net.h irc.h main.h rpc.h uibase.h ui.h noui.h init.h sha.h
-
-
-all: bitcoin.exe
-
-
-obj/%.o: %.cpp $(HEADERS)
-	g++ -c $(CFLAGS) -DGUI -o $@ $<
-
-obj/sha.o: sha.cpp sha.h
-	g++ -c $(CFLAGS) -O3 -o $@ $<
-
-obj/ui_res.o: ui.rc  rc/bitcoin.ico rc/check.ico rc/send16.bmp rc/send16mask.bmp rc/send16masknoshadow.bmp rc/send20.bmp rc/send20mask.bmp rc/addressbook16.bmp rc/addressbook16mask.bmp rc/addressbook20.bmp rc/addressbook20mask.bmp
-	windres $(DEFS) $(INCLUDEPATHS) -o $@ -i $<
+    script.h db.h net.h irc.h main.h rpc.h uibase.h ui.h noui.h init.h
 
 OBJS= \
     obj/util.o \
@@ -55,20 +42,36 @@
     obj/irc.o \
     obj/main.o \
     obj/rpc.o \
-    obj/init.o
+    obj/init.o \
+    cryptopp/obj/sha.o \
+    cryptopp/obj/cpu.o
+
+
+all: bitcoin.exe
+
 
-bitcoin.exe: $(OBJS) obj/ui.o obj/uibase.o obj/sha.o obj/ui_res.o
+obj/%.o: %.cpp $(HEADERS)
+	g++ -c $(CFLAGS) -DGUI -o $@ $<
+
+cryptopp/obj/%.o: cryptopp/%.cpp
+	g++ -c $(CFLAGS) -O3 -DCRYPTOPP_X86_ASM_AVAILABLE -o $@ $<
+
+obj/ui_res.o: ui.rc  rc/bitcoin.ico rc/check.ico rc/send16.bmp rc/send16mask.bmp rc/send16masknoshadow.bmp rc/send20.bmp rc/send20mask.bmp rc/addressbook16.bmp rc/addressbook16mask.bmp rc/addressbook20.bmp rc/addressbook20mask.bmp
+	windres $(DEFS) $(INCLUDEPATHS) -o $@ -i $<
+
+bitcoin.exe: $(OBJS) obj/ui.o obj/uibase.o obj/ui_res.o
 	g++ $(CFLAGS) -mwindows -Wl,--subsystem,windows -o $@ $(LIBPATHS) $^ $(WXLIBS) $(LIBS)
 
 
 obj/nogui/%.o: %.cpp $(HEADERS)
 	g++ -c $(CFLAGS) -o $@ $<
 
-bitcoind.exe: $(OBJS:obj/%=obj/nogui/%) obj/sha.o obj/ui_res.o
+bitcoind.exe: $(OBJS:obj/%=obj/nogui/%) obj/ui_res.o
 	g++ $(CFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS)
 
 
 clean:
 	-del /Q obj\*
 	-del /Q obj\nogui\*
+	-del /Q cryptopp\obj\*
 	-del /Q headers.h.gch
--- a/makefile.osx
+++ b/makefile.osx
@@ -29,17 +29,7 @@
 # ppc doesn't work because we don't support big-endian
 CFLAGS=-mmacosx-version-min=10.5 -arch i386 -arch x86_64 -O2 -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
 HEADERS=headers.h strlcpy.h serialize.h uint256.h util.h key.h bignum.h base58.h \
-    script.h db.h net.h irc.h main.h rpc.h uibase.h ui.h noui.h init.h sha.h
-
-
-all: bitcoin
-
-
-obj/%.o: %.cpp $(HEADERS)
-	g++ -c $(CFLAGS) -DGUI -o $@ $<
-
-obj/sha.o: sha.cpp sha.h
-	g++ -c $(CFLAGS) -O3 -o $@ $<
+    script.h db.h net.h irc.h main.h rpc.h uibase.h ui.h noui.h init.h
 
 OBJS= \
     obj/util.o \
@@ -49,16 +39,28 @@
     obj/irc.o \
     obj/main.o \
     obj/rpc.o \
-    obj/init.o
+    obj/init.o \
+    cryptopp/obj/sha.o \
+    cryptopp/obj/cpu.o
 	
-bitcoin: $(OBJS) obj/ui.o obj/uibase.o obj/sha.o
+
+all: bitcoin
+
+
+obj/%.o: %.cpp $(HEADERS)
+	g++ -c $(CFLAGS) -DGUI -o $@ $<
+
+cryptopp/obj/%.o: cryptopp/%.cpp
+	g++ -c $(CFLAGS) -O3 -o $@ $<
+
+bitcoin: $(OBJS) obj/ui.o obj/uibase.o
 	g++ $(CFLAGS) -o $@ $(LIBPATHS) $^ $(WXLIBS) $(LIBS)
 
 
 obj/nogui/%.o: %.cpp $(HEADERS)
 	g++ -c $(CFLAGS) -o $@ $<
 
-bitcoind: $(OBJS:obj/%=obj/nogui/%) obj/sha.o
+bitcoind: $(OBJS:obj/%=obj/nogui/%)
 	g++ $(CFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS)
 
 
--- a/makefile.unix
+++ b/makefile.unix
@@ -33,7 +33,19 @@
 DEBUGFLAGS=-g -D__WXDEBUG__
 CFLAGS=-O2 -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
 HEADERS=headers.h strlcpy.h serialize.h uint256.h util.h key.h bignum.h base58.h \
-    script.h db.h net.h irc.h main.h rpc.h uibase.h ui.h noui.h init.h sha.h
+    script.h db.h net.h irc.h main.h rpc.h uibase.h ui.h noui.h init.h
+
+OBJS= \
+    obj/util.o \
+    obj/script.o \
+    obj/db.o \
+    obj/net.o \
+    obj/irc.o \
+    obj/main.o \
+    obj/rpc.o \
+    obj/init.o \
+    cryptopp/obj/sha.o \
+    cryptopp/obj/cpu.o
 
 
 all: bitcoin
@@ -45,31 +57,22 @@
 obj/%.o: %.cpp $(HEADERS) headers.h.gch
 	g++ -c $(CFLAGS) -DGUI -o $@ $<
 
-obj/sha.o: sha.cpp sha.h
+cryptopp/obj/%.o: cryptopp/%.cpp
 	g++ -c $(CFLAGS) -O3 -o $@ $<
 
-OBJS= \
-    obj/util.o \
-    obj/script.o \
-    obj/db.o \
-    obj/net.o \
-    obj/irc.o \
-    obj/main.o \
-    obj/rpc.o \
-    obj/init.o
-
-bitcoin: $(OBJS) obj/ui.o obj/uibase.o obj/sha.o
+bitcoin: $(OBJS) obj/ui.o obj/uibase.o
 	g++ $(CFLAGS) -o $@ $(LIBPATHS) $^ $(WXLIBS) $(LIBS)
 
 
 obj/nogui/%.o: %.cpp $(HEADERS)
 	g++ -c $(CFLAGS) -o $@ $<
 
-bitcoind: $(OBJS:obj/%=obj/nogui/%) obj/sha.o
+bitcoind: $(OBJS:obj/%=obj/nogui/%)
 	g++ $(CFLAGS) -o $@ $(LIBPATHS) $^ $(LIBS)
 
 
 clean:
 	-rm -f obj/*.o
 	-rm -f obj/nogui/*.o
+	-rm -f cryptopp/obj/*.o
 	-rm -f headers.h.gch
--- a/makefile.vc
+++ b/makefile.vc
@@ -28,17 +28,29 @@
   kernel32.lib user32.lib gdi32.lib comdlg32.lib winspool.lib winmm.lib shell32.lib comctl32.lib ole32.lib oleaut32.lib uuid.lib rpcrt4.lib advapi32.lib ws2_32.lib shlwapi.lib
 
 DEFS=/DWIN32 /D__WXMSW__ /D_WINDOWS /DNOPCH
-DEBUGFLAGS=/Zi /Od /D__WXDEBUG__
+DEBUGFLAGS=/Zi /D__WXDEBUG__
 CFLAGS=/c /nologo /MDd /EHsc /GR /Zm300 $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
 HEADERS=headers.h strlcpy.h serialize.h uint256.h util.h key.h bignum.h base58.h \
-    script.h db.h net.h irc.h main.h rpc.h uibase.h ui.h noui.h init.h sha.h
+    script.h db.h net.h irc.h main.h rpc.h uibase.h ui.h noui.h init.h
+
+OBJS= \
+    obj\util.obj \
+    obj\script.obj \
+    obj\db.obj \
+    obj\net.obj \
+    obj\irc.obj \
+    obj\main.obj \
+    obj\rpc.obj \
+    obj\init.obj \
+    cryptopp\obj\sha.obj \
+    cryptopp\obj\cpu.obj
 
 
 all: bitcoin.exe
 
 
 .cpp{obj}.obj:
-	cl $(CFLAGS) /DGUI /Fo$@ %s
+    cl $(CFLAGS) /DGUI /Fo$@ %s
 
 obj\util.obj: $(HEADERS)
 
@@ -60,28 +72,21 @@
 
 obj\uibase.obj: $(HEADERS)
 
-obj\sha.obj: sha.cpp sha.h
-	cl $(CFLAGS) /O2 /Fo$@ %s
+cryptopp\obj\sha.obj: cryptopp\sha.cpp
+    cl $(CFLAGS) /O2 /Fo$@ %s
+
+cryptopp\obj\cpu.obj: cryptopp\cpu.cpp
+    cl $(CFLAGS) /O2 /Fo$@ %s
 
 obj\ui.res: ui.rc  rc/bitcoin.ico rc/check.ico rc/send16.bmp rc/send16mask.bmp rc/send16masknoshadow.bmp rc/send20.bmp rc/send20mask.bmp rc/addressbook16.bmp rc/addressbook16mask.bmp rc/addressbook20.bmp rc/addressbook20mask.bmp
-	rc $(INCLUDEPATHS) $(DEFS) /Fo$@ %s
+    rc $(INCLUDEPATHS) $(DEFS) /Fo$@ %s
 
-OBJS= \
-    obj\util.obj \
-    obj\script.obj \
-    obj\db.obj \
-    obj\net.obj \
-    obj\irc.obj \
-    obj\main.obj \
-    obj\rpc.obj \
-    obj\init.obj
-
-bitcoin.exe: $(OBJS) obj\ui.obj obj\uibase.obj obj\sha.obj obj\ui.res
+bitcoin.exe: $(OBJS) obj\ui.obj obj\uibase.obj obj\ui.res
     link /nologo /DEBUG /SUBSYSTEM:WINDOWS /OUT:$@ $(LIBPATHS) $** $(WXLIBS) $(LIBS)
 
 
 .cpp{obj\nogui}.obj:
-	cl $(CFLAGS) /Fo$@ %s
+    cl $(CFLAGS) /Fo$@ %s
 
 obj\nogui\util.obj: $(HEADERS)
 
@@ -99,11 +104,13 @@
 
 obj\nogui\init.obj: $(HEADERS)
 
-bitcoind.exe: $(OBJS:obj\=obj\nogui\) obj\sha.obj obj\ui.res
-	link /nologo /DEBUG /OUT:$@ $(LIBPATHS) $** $(LIBS)
+bitcoind.exe: $(OBJS:obj\=obj\nogui\) obj\ui.res
+    link /nologo /DEBUG /OUT:$@ $(LIBPATHS) $** $(LIBS)
 
 
 clean:
-	-del /Q obj\*
-	-del *.ilk
-	-del *.pdb
+    -del /Q obj\*
+    -del /Q obj\nogui\*
+    -del /Q cryptopp\obj\*
+    -del /Q *.ilk
+    -del /Q *.pdb
deleted file mode 100644
--- a/sha.cpp
+++ /dev/null
@@ -1,554 +0,0 @@
-// This file is public domain
-// SHA routines extracted as a standalone file from:
-// Crypto++: a C++ Class Library of Cryptographic Schemes
-// Version 5.5.2 (9/24/2007)
-// http://www.cryptopp.com
-
-// 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 <assert.h>
-#include <memory.h>
-#include "sha.h"
-
-namespace CryptoPP
-{
-
-// 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))
-
-void SHA1::InitState(HashWordType *state)
-{
-    state[0] = 0x67452301L;
-    state[1] = 0xEFCDAB89L;
-    state[2] = 0x98BADCFEL;
-    state[3] = 0x10325476L;
-    state[4] = 0xC3D2E1F0L;
-}
-
-#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 SHA1::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;
-}
-
-// end of Steve Reid's code
-
-// *************************************************************
-
-void SHA224::InitState(HashWordType *state)
-{
-    static const word32 s[8] = {0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4};
-    memcpy(state, s, sizeof(s));
-}
-
-void SHA256::InitState(HashWordType *state)
-{
-    static const word32 s[8] = {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};
-    memcpy(state, s, sizeof(s));
-}
-
-static const word32 SHA256_K[64] = {
-    0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
-    0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
-    0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
-    0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
-    0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
-    0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
-    0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
-    0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
-    0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
-    0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
-    0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
-    0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
-    0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
-    0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
-    0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
-    0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
-};
-
-#define blk2(i) (W[i&15]+=s1(W[(i-2)&15])+W[(i-7)&15]+s0(W[(i-15)&15]))
-
-#define Ch(x,y,z) (z^(x&(y^z)))
-#define Maj(x,y,z) ((x&y)|(z&(x|y)))
-
-#define a(i) T[(0-i)&7]
-#define b(i) T[(1-i)&7]
-#define c(i) T[(2-i)&7]
-#define d(i) T[(3-i)&7]
-#define e(i) T[(4-i)&7]
-#define f(i) T[(5-i)&7]
-#define g(i) T[(6-i)&7]
-#define h(i) T[(7-i)&7]
-
-#define R(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+SHA256_K[i+j]+(j?blk2(i):blk0(i));\
-    d(i)+=h(i);h(i)+=S0(a(i))+Maj(a(i),b(i),c(i))
-
-// for SHA256
-#define S0(x) (rotrFixed(x,2)^rotrFixed(x,13)^rotrFixed(x,22))
-#define S1(x) (rotrFixed(x,6)^rotrFixed(x,11)^rotrFixed(x,25))
-#define s0(x) (rotrFixed(x,7)^rotrFixed(x,18)^(x>>3))
-#define s1(x) (rotrFixed(x,17)^rotrFixed(x,19)^(x>>10))
-
-void SHA256::Transform(word32 *state, const word32 *data)
-{
-    word32 W[16];
-    word32 T[8];
-    /* Copy context->state[] to working vars */
-    memcpy(T, state, sizeof(T));
-    /* 64 operations, partially loop unrolled */
-    for (unsigned int j=0; j<64; j+=16)
-    {
-        R( 0); R( 1); R( 2); R( 3);
-        R( 4); R( 5); R( 6); R( 7);
-        R( 8); R( 9); R(10); R(11);
-        R(12); R(13); R(14); R(15);
-    }
-    /* Add the working vars back into context.state[] */
-    state[0] += a(0);
-    state[1] += b(0);
-    state[2] += c(0);
-    state[3] += d(0);
-    state[4] += e(0);
-    state[5] += f(0);
-    state[6] += g(0);
-    state[7] += h(0);
-}
-
-/*
-// smaller but slower
-void SHA256_Transform(word32 *state, const word32 *data)
-{
-    word32 T[20];
-    word32 W[32];
-    unsigned int i = 0, j = 0;
-    word32 *t = T+8;
-
-    memcpy(t, state, 8*4);
-    word32 e = t[4], a = t[0];
-
-    do
-    {
-        word32 w = data[j];
-        W[j] = w;
-        w += K[j];
-        w += t[7];
-        w += S1(e);
-        w += Ch(e, t[5], t[6]);
-        e = t[3] + w;
-        t[3] = t[3+8] = e;
-        w += S0(t[0]);
-        a = w + Maj(a, t[1], t[2]);
-        t[-1] = t[7] = a;
-        --t;
-        ++j;
-        if (j%8 == 0)
-            t += 8;
-    } while (j<16);
-
-    do
-    {
-        i = j&0xf;
-        word32 w = s1(W[i+16-2]) + s0(W[i+16-15]) + W[i] + W[i+16-7];
-        W[i+16] = W[i] = w;
-        w += K[j];
-        w += t[7];
-        w += S1(e);
-        w += Ch(e, t[5], t[6]);
-        e = t[3] + w;
-        t[3] = t[3+8] = e;
-        w += S0(t[0]);
-        a = w + Maj(a, t[1], t[2]);
-        t[-1] = t[7] = a;
-
-        w = s1(W[(i+1)+16-2]) + s0(W[(i+1)+16-15]) + W[(i+1)] + W[(i+1)+16-7];
-        W[(i+1)+16] = W[(i+1)] = w;
-        w += K[j+1];
-        w += (t-1)[7];
-        w += S1(e);
-        w += Ch(e, (t-1)[5], (t-1)[6]);
-        e = (t-1)[3] + w;
-        (t-1)[3] = (t-1)[3+8] = e;
-        w += S0((t-1)[0]);
-        a = w + Maj(a, (t-1)[1], (t-1)[2]);
-        (t-1)[-1] = (t-1)[7] = a;
-
-        t-=2;
-        j+=2;
-        if (j%8 == 0)
-            t += 8;
-    } while (j<64);
-
-    state[0] += a;
-    state[1] += t[1];
-    state[2] += t[2];
-    state[3] += t[3];
-    state[4] += e;
-    state[5] += t[5];
-    state[6] += t[6];
-    state[7] += t[7];
-}
-*/
-
-#undef S0
-#undef S1
-#undef s0
-#undef s1
-#undef R
-
-// *************************************************************
-
-#ifdef WORD64_AVAILABLE
-
-void SHA384::InitState(HashWordType *state)
-{
-    static const word64 s[8] = {
-        W64LIT(0xcbbb9d5dc1059ed8), W64LIT(0x629a292a367cd507),
-        W64LIT(0x9159015a3070dd17), W64LIT(0x152fecd8f70e5939),
-        W64LIT(0x67332667ffc00b31), W64LIT(0x8eb44a8768581511),
-        W64LIT(0xdb0c2e0d64f98fa7), W64LIT(0x47b5481dbefa4fa4)};
-    memcpy(state, s, sizeof(s));
-}
-
-void SHA512::InitState(HashWordType *state)
-{
-    static const word64 s[8] = {
-        W64LIT(0x6a09e667f3bcc908), W64LIT(0xbb67ae8584caa73b),
-        W64LIT(0x3c6ef372fe94f82b), W64LIT(0xa54ff53a5f1d36f1),
-        W64LIT(0x510e527fade682d1), W64LIT(0x9b05688c2b3e6c1f),
-        W64LIT(0x1f83d9abfb41bd6b), W64LIT(0x5be0cd19137e2179)};
-    memcpy(state, s, sizeof(s));
-}
-
-CRYPTOPP_ALIGN_DATA(16) static const word64 SHA512_K[80] CRYPTOPP_SECTION_ALIGN16 = {
-    W64LIT(0x428a2f98d728ae22), W64LIT(0x7137449123ef65cd),
-    W64LIT(0xb5c0fbcfec4d3b2f), W64LIT(0xe9b5dba58189dbbc),
-    W64LIT(0x3956c25bf348b538), W64LIT(0x59f111f1b605d019),
-    W64LIT(0x923f82a4af194f9b), W64LIT(0xab1c5ed5da6d8118),
-    W64LIT(0xd807aa98a3030242), W64LIT(0x12835b0145706fbe),
-    W64LIT(0x243185be4ee4b28c), W64LIT(0x550c7dc3d5ffb4e2),
-    W64LIT(0x72be5d74f27b896f), W64LIT(0x80deb1fe3b1696b1),
-    W64LIT(0x9bdc06a725c71235), W64LIT(0xc19bf174cf692694),
-    W64LIT(0xe49b69c19ef14ad2), W64LIT(0xefbe4786384f25e3),
-    W64LIT(0x0fc19dc68b8cd5b5), W64LIT(0x240ca1cc77ac9c65),
-    W64LIT(0x2de92c6f592b0275), W64LIT(0x4a7484aa6ea6e483),
-    W64LIT(0x5cb0a9dcbd41fbd4), W64LIT(0x76f988da831153b5),
-    W64LIT(0x983e5152ee66dfab), W64LIT(0xa831c66d2db43210),
-    W64LIT(0xb00327c898fb213f), W64LIT(0xbf597fc7beef0ee4),
-    W64LIT(0xc6e00bf33da88fc2), W64LIT(0xd5a79147930aa725),
-    W64LIT(0x06ca6351e003826f), W64LIT(0x142929670a0e6e70),
-    W64LIT(0x27b70a8546d22ffc), W64LIT(0x2e1b21385c26c926),
-    W64LIT(0x4d2c6dfc5ac42aed), W64LIT(0x53380d139d95b3df),
-    W64LIT(0x650a73548baf63de), W64LIT(0x766a0abb3c77b2a8),
-    W64LIT(0x81c2c92e47edaee6), W64LIT(0x92722c851482353b),
-    W64LIT(0xa2bfe8a14cf10364), W64LIT(0xa81a664bbc423001),
-    W64LIT(0xc24b8b70d0f89791), W64LIT(0xc76c51a30654be30),
-    W64LIT(0xd192e819d6ef5218), W64LIT(0xd69906245565a910),
-    W64LIT(0xf40e35855771202a), W64LIT(0x106aa07032bbd1b8),
-    W64LIT(0x19a4c116b8d2d0c8), W64LIT(0x1e376c085141ab53),
-    W64LIT(0x2748774cdf8eeb99), W64LIT(0x34b0bcb5e19b48a8),
-    W64LIT(0x391c0cb3c5c95a63), W64LIT(0x4ed8aa4ae3418acb),
-    W64LIT(0x5b9cca4f7763e373), W64LIT(0x682e6ff3d6b2b8a3),
-    W64LIT(0x748f82ee5defb2fc), W64LIT(0x78a5636f43172f60),
-    W64LIT(0x84c87814a1f0ab72), W64LIT(0x8cc702081a6439ec),
-    W64LIT(0x90befffa23631e28), W64LIT(0xa4506cebde82bde9),
-    W64LIT(0xbef9a3f7b2c67915), W64LIT(0xc67178f2e372532b),
-    W64LIT(0xca273eceea26619c), W64LIT(0xd186b8c721c0c207),
-    W64LIT(0xeada7dd6cde0eb1e), W64LIT(0xf57d4f7fee6ed178),
-    W64LIT(0x06f067aa72176fba), W64LIT(0x0a637dc5a2c898a6),
-    W64LIT(0x113f9804bef90dae), W64LIT(0x1b710b35131c471b),
-    W64LIT(0x28db77f523047d84), W64LIT(0x32caab7b40c72493),
-    W64LIT(0x3c9ebe0a15c9bebc), W64LIT(0x431d67c49c100d4c),
-    W64LIT(0x4cc5d4becb3e42b6), W64LIT(0x597f299cfc657e2a),
-    W64LIT(0x5fcb6fab3ad6faec), W64LIT(0x6c44198c4a475817)
-};
-
-#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && CRYPTOPP_BOOL_X86
-// put assembly version in separate function, otherwise MSVC 2005 SP1 doesn't generate correct code for the non-assembly version
-CRYPTOPP_NAKED static void CRYPTOPP_FASTCALL SHA512_SSE2_Transform(word64 *state, const word64 *data)
-{
-#ifdef __GNUC__
-    __asm__ __volatile__
-    (
-        ".intel_syntax noprefix;"
-    AS1(    push    ebx)
-    AS2(    mov     ebx, eax)
-#else
-    AS1(    push    ebx)
-    AS1(    push    esi)
-    AS1(    push    edi)
-    AS2(    lea     ebx, SHA512_K)
-#endif
-
-    AS2(    mov     eax, esp)
-    AS2(    and     esp, 0xfffffff0)
-    AS2(    sub     esp, 27*16)             // 17*16 for expanded data, 20*8 for state
-    AS1(    push    eax)
-    AS2(    xor     eax, eax)
-    AS2(    lea     edi, [esp+4+8*8])       // start at middle of state buffer. will decrement pointer each round to avoid copying
-    AS2(    lea     esi, [esp+4+20*8+8])    // 16-byte alignment, then add 8
-
-    AS2(    movq    mm4, [ecx+0*8])
-    AS2(    movq    [edi+0*8], mm4)
-    AS2(    movq    mm0, [ecx+1*8])
-    AS2(    movq    [edi+1*8], mm0)
-    AS2(    movq    mm0, [ecx+2*8])
-    AS2(    movq    [edi+2*8], mm0)
-    AS2(    movq    mm0, [ecx+3*8])
-    AS2(    movq    [edi+3*8], mm0)
-    AS2(    movq    mm5, [ecx+4*8])
-    AS2(    movq    [edi+4*8], mm5)
-    AS2(    movq    mm0, [ecx+5*8])
-    AS2(    movq    [edi+5*8], mm0)
-    AS2(    movq    mm0, [ecx+6*8])
-    AS2(    movq    [edi+6*8], mm0)
-    AS2(    movq    mm0, [ecx+7*8])
-    AS2(    movq    [edi+7*8], mm0)
-    ASJ(    jmp,    0, f)
-
-#define SSE2_S0_S1(r, a, b, c)  \
-    AS2(    movq    mm6, r)\
-    AS2(    psrlq   r, a)\
-    AS2(    movq    mm7, r)\
-    AS2(    psllq   mm6, 64-c)\
-    AS2(    pxor    mm7, mm6)\
-    AS2(    psrlq   r, b-a)\
-    AS2(    pxor    mm7, r)\
-    AS2(    psllq   mm6, c-b)\
-    AS2(    pxor    mm7, mm6)\
-    AS2(    psrlq   r, c-b)\
-    AS2(    pxor    r, mm7)\
-    AS2(    psllq   mm6, b-a)\
-    AS2(    pxor    r, mm6)
-
-#define SSE2_s0(r, a, b, c) \
-    AS2(    movdqa  xmm6, r)\
-    AS2(    psrlq   r, a)\
-    AS2(    movdqa  xmm7, r)\
-    AS2(    psllq   xmm6, 64-c)\
-    AS2(    pxor    xmm7, xmm6)\
-    AS2(    psrlq   r, b-a)\
-    AS2(    pxor    xmm7, r)\
-    AS2(    psrlq   r, c-b)\
-    AS2(    pxor    r, xmm7)\
-    AS2(    psllq   xmm6, c-a)\
-    AS2(    pxor    r, xmm6)
-
-#define SSE2_s1(r, a, b, c) \
-    AS2(    movdqa  xmm6, r)\
-    AS2(    psrlq   r, a)\
-    AS2(    movdqa  xmm7, r)\
-    AS2(    psllq   xmm6, 64-c)\
-    AS2(    pxor    xmm7, xmm6)\
-    AS2(    psrlq   r, b-a)\
-    AS2(    pxor    xmm7, r)\
-    AS2(    psllq   xmm6, c-b)\
-    AS2(    pxor    xmm7, xmm6)\
-    AS2(    psrlq   r, c-b)\
-    AS2(    pxor    r, xmm7)
-
-    ASL(SHA512_Round)
-    // k + w is in mm0, a is in mm4, e is in mm5
-    AS2(    paddq   mm0, [edi+7*8])     // h
-    AS2(    movq    mm2, [edi+5*8])     // f
-    AS2(    movq    mm3, [edi+6*8])     // g
-    AS2(    pxor    mm2, mm3)
-    AS2(    pand    mm2, mm5)
-    SSE2_S0_S1(mm5,14,18,41)
-    AS2(    pxor    mm2, mm3)
-    AS2(    paddq   mm0, mm2)           // h += Ch(e,f,g)
-    AS2(    paddq   mm5, mm0)           // h += S1(e)
-    AS2(    movq    mm2, [edi+1*8])     // b
-    AS2(    movq    mm1, mm2)
-    AS2(    por     mm2, mm4)
-    AS2(    pand    mm2, [edi+2*8])     // c
-    AS2(    pand    mm1, mm4)
-    AS2(    por     mm1, mm2)
-    AS2(    paddq   mm1, mm5)           // temp = h + Maj(a,b,c)
-    AS2(    paddq   mm5, [edi+3*8])     // e = d + h
-    AS2(    movq    [edi+3*8], mm5)
-    AS2(    movq    [edi+11*8], mm5)
-    SSE2_S0_S1(mm4,28,34,39)            // S0(a)
-    AS2(    paddq   mm4, mm1)           // a = temp + S0(a)
-    AS2(    movq    [edi-8], mm4)
-    AS2(    movq    [edi+7*8], mm4)
-    AS1(    ret)
-
-    // first 16 rounds
-    ASL(0)
-    AS2(    movq    mm0, [edx+eax*8])
-    AS2(    movq    [esi+eax*8], mm0)
-    AS2(    movq    [esi+eax*8+16*8], mm0)
-    AS2(    paddq   mm0, [ebx+eax*8])
-    ASC(    call,   SHA512_Round)
-    AS1(    inc     eax)
-    AS2(    sub     edi, 8)
-    AS2(    test    eax, 7)
-    ASJ(    jnz,    0, b)
-    AS2(    add     edi, 8*8)
-    AS2(    cmp     eax, 16)
-    ASJ(    jne,    0, b)
-
-    // rest of the rounds
-    AS2(    movdqu  xmm0, [esi+(16-2)*8])
-    ASL(1)
-    // data expansion, W[i-2] already in xmm0
-    AS2(    movdqu  xmm3, [esi])
-    AS2(    paddq   xmm3, [esi+(16-7)*8])
-    AS2(    movdqa  xmm2, [esi+(16-15)*8])
-    SSE2_s1(xmm0, 6, 19, 61)
-    AS2(    paddq   xmm0, xmm3)
-    SSE2_s0(xmm2, 1, 7, 8)
-    AS2(    paddq   xmm0, xmm2)
-    AS2(    movdq2q mm0, xmm0)
-    AS2(    movhlps xmm1, xmm0)
-    AS2(    paddq   mm0, [ebx+eax*8])
-    AS2(    movlps  [esi], xmm0)
-    AS2(    movlps  [esi+8], xmm1)
-    AS2(    movlps  [esi+8*16], xmm0)
-    AS2(    movlps  [esi+8*17], xmm1)
-    // 2 rounds
-    ASC(    call,   SHA512_Round)
-    AS2(    sub     edi, 8)
-    AS2(    movdq2q mm0, xmm1)
-    AS2(    paddq   mm0, [ebx+eax*8+8])
-    ASC(    call,   SHA512_Round)
-    // update indices and loop
-    AS2(    add     esi, 16)
-    AS2(    add     eax, 2)
-    AS2(    sub     edi, 8)
-    AS2(    test    eax, 7)
-    ASJ(    jnz,    1, b)
-    // do housekeeping every 8 rounds
-    AS2(    mov     esi, 0xf)
-    AS2(    and     esi, eax)
-    AS2(    lea     esi, [esp+4+20*8+8+esi*8])
-    AS2(    add     edi, 8*8)
-    AS2(    cmp     eax, 80)
-    ASJ(    jne,    1, b)
-
-#define SSE2_CombineState(i)    \
-    AS2(    movq    mm0, [edi+i*8])\
-    AS2(    paddq   mm0, [ecx+i*8])\
-    AS2(    movq    [ecx+i*8], mm0)
-
-    SSE2_CombineState(0)
-    SSE2_CombineState(1)
-    SSE2_CombineState(2)
-    SSE2_CombineState(3)
-    SSE2_CombineState(4)
-    SSE2_CombineState(5)
-    SSE2_CombineState(6)
-    SSE2_CombineState(7)
-
-    AS1(    pop     esp)
-    AS1(    emms)
-
-#if defined(__GNUC__)
-    AS1(    pop     ebx)
-    ".att_syntax prefix;"
-        :
-        : "a" (SHA512_K), "c" (state), "d" (data)
-        : "%esi", "%edi", "memory", "cc"
-    );
-#else
-    AS1(    pop     edi)
-    AS1(    pop     esi)
-    AS1(    pop     ebx)
-    AS1(    ret)
-#endif
-}
-#endif  // #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
-
-void SHA512::Transform(word64 *state, const word64 *data)
-{
-#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && CRYPTOPP_BOOL_X86
-    if (HasSSE2())
-    {
-        SHA512_SSE2_Transform(state, data);
-        return;
-    }
-#endif
-
-#define S0(x) (rotrFixed(x,28)^rotrFixed(x,34)^rotrFixed(x,39))
-#define S1(x) (rotrFixed(x,14)^rotrFixed(x,18)^rotrFixed(x,41))
-#define s0(x) (rotrFixed(x,1)^rotrFixed(x,8)^(x>>7))
-#define s1(x) (rotrFixed(x,19)^rotrFixed(x,61)^(x>>6))
-
-#define R(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+SHA512_K[i+j]+(j?blk2(i):blk0(i));\
-    d(i)+=h(i);h(i)+=S0(a(i))+Maj(a(i),b(i),c(i))
-
-    word64 W[16];
-    word64 T[8];
-    /* Copy context->state[] to working vars */
-    memcpy(T, state, sizeof(T));
-    /* 80 operations, partially loop unrolled */
-    for (unsigned int j=0; j<80; j+=16)
-    {
-        R( 0); R( 1); R( 2); R( 3);
-        R( 4); R( 5); R( 6); R( 7);
-        R( 8); R( 9); R(10); R(11);
-        R(12); R(13); R(14); R(15);
-    }
-    /* Add the working vars back into context.state[] */
-    state[0] += a(0);
-    state[1] += b(0);
-    state[2] += c(0);
-    state[3] += d(0);
-    state[4] += e(0);
-    state[5] += f(0);
-    state[6] += g(0);
-    state[7] += h(0);
-}
-
-#endif
-
-}
deleted file mode 100644
--- a/sha.h
+++ /dev/null
@@ -1,177 +0,0 @@
-// This file is public domain
-// SHA routines extracted as a standalone file from:
-// Crypto++: a C++ Class Library of Cryptographic Schemes
-// Version 5.5.2 (9/24/2007)
-// http://www.cryptopp.com
-#ifndef CRYPTOPP_SHA_H
-#define CRYPTOPP_SHA_H
-#include <stdlib.h>
-
-namespace CryptoPP
-{
-
-//
-// Dependencies
-//
-
-typedef unsigned char byte;
-typedef unsigned short word16;
-typedef unsigned int word32;
-#if defined(_MSC_VER) || defined(__BORLANDC__)
-typedef unsigned __int64 word64;
-#else
-typedef unsigned long long word64;
-#endif
-
-template <class T> inline T rotlFixed(T x, unsigned int y)
-{
-    assert(y < sizeof(T)*8);
-    return T((x<<y) | (x>>(sizeof(T)*8-y)));
-}
-
-template <class T> inline T rotrFixed(T x, unsigned int y)
-{
-    assert(y < sizeof(T)*8);
-    return T((x>>y) | (x<<(sizeof(T)*8-y)));
-}
-
-// ************** endian reversal ***************
-
-#ifdef _MSC_VER
-    #if _MSC_VER >= 1400
-        #define CRYPTOPP_FAST_ROTATE(x) 1
-    #elif _MSC_VER >= 1300
-        #define CRYPTOPP_FAST_ROTATE(x) ((x) == 32 | (x) == 64)
-    #else
-        #define CRYPTOPP_FAST_ROTATE(x) ((x) == 32)
-    #endif
-#elif (defined(__MWERKS__) && TARGET_CPU_PPC) || \
-    (defined(__GNUC__) && (defined(_ARCH_PWR2) || defined(_ARCH_PWR) || defined(_ARCH_PPC) || defined(_ARCH_PPC64) || defined(_ARCH_COM)))
-    #define CRYPTOPP_FAST_ROTATE(x) ((x) == 32)
-#elif defined(__GNUC__) && (CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X86) // depend on GCC's peephole optimization to generate rotate instructions
-    #define CRYPTOPP_FAST_ROTATE(x) 1
-#else
-    #define CRYPTOPP_FAST_ROTATE(x) 0
-#endif
-
-inline byte ByteReverse(byte value)
-{
-    return value;
-}
-
-inline word16 ByteReverse(word16 value)
-{
-#ifdef CRYPTOPP_BYTESWAP_AVAILABLE
-    return bswap_16(value);
-#elif defined(_MSC_VER) && _MSC_VER >= 1300
-    return _byteswap_ushort(value);
-#else
-    return rotlFixed(value, 8U);
-#endif
-}
-
-inline word32 ByteReverse(word32 value)
-{
-#if defined(__GNUC__)
-    __asm__ ("bswap %0" : "=r" (value) : "0" (value));
-    return value;
-#elif defined(CRYPTOPP_BYTESWAP_AVAILABLE)
-    return bswap_32(value);
-#elif defined(__MWERKS__) && TARGET_CPU_PPC
-    return (word32)__lwbrx(&value,0);
-#elif _MSC_VER >= 1400 || (_MSC_VER >= 1300 && !defined(_DLL))
-    return _byteswap_ulong(value);
-#elif CRYPTOPP_FAST_ROTATE(32)
-    // 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)
-{
-#if defined(__GNUC__) && defined(__x86_64__)
-    __asm__ ("bswap %0" : "=r" (value) : "0" (value));
-    return value;
-#elif defined(CRYPTOPP_BYTESWAP_AVAILABLE)
-    return bswap_64(value);
-#elif defined(_MSC_VER) && _MSC_VER >= 1300
-    return _byteswap_uint64(value);
-#elif defined(CRYPTOPP_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
-
-
-//
-// SHA
-//
-
-// http://www.weidai.com/scan-mirror/md.html#SHA-1
-class SHA1
-{
-public:
-    typedef word32 HashWordType;
-    static void InitState(word32 *state);
-    static void Transform(word32 *digest, const word32 *data);
-    static const char * StaticAlgorithmName() {return "SHA-1";}
-};
-
-typedef SHA1 SHA;   // for backwards compatibility
-
-// implements the SHA-256 standard
-class SHA256
-{
-public:
-    typedef word32 HashWordType;
-    static void InitState(word32 *state);
-    static void Transform(word32 *digest, const word32 *data);
-    static const char * StaticAlgorithmName() {return "SHA-256";}
-};
-
-// implements the SHA-224 standard
-class SHA224
-{
-public:
-    typedef word32 HashWordType;
-    static void InitState(word32 *state);
-    static void Transform(word32 *digest, const word32 *data) {SHA256::Transform(digest, data);}
-    static const char * StaticAlgorithmName() {return "SHA-224";}
-};
-
-#ifdef WORD64_AVAILABLE
-
-// implements the SHA-512 standard
-class SHA512
-{
-public:
-    typedef word64 HashWordType;
-    static void InitState(word64 *state);
-    static void Transform(word64 *digest, const word64 *data);
-    static const char * StaticAlgorithmName() {return "SHA-512";}
-};
-
-// implements the SHA-384 standard
-class SHA384
-{
-public:
-    typedef word64 HashWordType;
-    static void InitState(word64 *state);
-    static void Transform(word64 *digest, const word64 *data) {SHA512::Transform(digest, data);}
-    static const char * StaticAlgorithmName() {return "SHA-384";}
-};
-
-#endif
-
-}
-
-#endif
--- a/util.h
+++ b/util.h
@@ -54,6 +54,20 @@
     return (T&)val;
 }
 
+// Align by increasing pointer, must have extra space at end of buffer
+template <size_t nBytes, typename T>
+T* alignup(T* p)
+{
+    union
+    {
+        T* ptr;
+        size_t n;
+    } u;
+    u.ptr = p;
+    u.n = (u.n + (nBytes-1)) & ~(nBytes-1);
+    return u.ptr;
+}
+
 #ifdef __WXMSW__
 #define MSG_NOSIGNAL        0
 #define MSG_DONTWAIT        0