Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

default.cpp

00001 // default.cpp - written and placed in the public domain by Wei Dai
00002 
00003 #include "pch.h"
00004 #include "default.h"
00005 #include "cbc.h"
00006 #include "queue.h"
00007 #include <time.h>
00008 #include <memory>
00009 
00010 NAMESPACE_BEGIN(CryptoPP)
00011 
00012 static const unsigned int MASH_ITERATIONS = 200;
00013 static const unsigned int SALTLENGTH = 8;
00014 static const unsigned int BLOCKSIZE = Default_ECB_Encryption::BLOCKSIZE;
00015 static const unsigned int KEYLENGTH = Default_ECB_Encryption::DEFAULT_KEYLENGTH;
00016 
00017 // The purpose of this function Mash() is to take an arbitrary length input
00018 // string and *deterministicly* produce an arbitrary length output string such
00019 // that (1) it looks random, (2) no information about the input is
00020 // deducible from it, and (3) it contains as much entropy as it can hold, or
00021 // the amount of entropy in the input string, whichever is smaller.
00022 
00023 static void Mash(const byte *in, word16 inLen, byte *out, word16 outLen, int iterations)
00024 {
00025         unsigned int bufSize = (outLen-1+DefaultHashModule::DIGESTSIZE-((outLen-1)%DefaultHashModule::DIGESTSIZE));
00026 
00027         // ASSERT: bufSize == (the smallest multiple of DIGESTSIZE that is >= outLen)
00028 
00029         byte b[2];
00030         SecByteBlock buf(bufSize);
00031         SecByteBlock outBuf(bufSize);
00032         DefaultHashModule hash;
00033 
00034         unsigned int i;
00035         for(i=0; i<outLen; i+=DefaultHashModule::DIGESTSIZE)
00036         {
00037                 b[0] = (byte) i >> 8;
00038                 b[1] = (byte) i;
00039                 hash.Update(b, 2);
00040                 hash.Update(in, inLen);
00041                 hash.Final(outBuf+i);
00042         }
00043 
00044         while (iterations-- > 1)
00045         {
00046                 memcpy(buf, outBuf, bufSize);
00047                 for (i=0; i<bufSize; i+=DefaultHashModule::DIGESTSIZE)
00048                 {
00049                         b[0] = (byte) i >> 8;
00050                         b[1] = (byte) i;
00051                         hash.Update(b, 2);
00052                         hash.Update(buf, bufSize);
00053                         hash.Final(outBuf+i);
00054                 }
00055         }
00056 
00057         memcpy(out, outBuf, outLen);
00058 }
00059 
00060 static void GenerateKeyIV(const byte *passphrase, unsigned int passphraseLength, const byte *salt, unsigned int saltLength, byte *key, byte *IV)
00061 {
00062         SecByteBlock temp(passphraseLength+saltLength);
00063         memcpy(temp, passphrase, passphraseLength);
00064         memcpy(temp+passphraseLength, salt, saltLength);
00065         SecByteBlock keyIV(KEYLENGTH+BLOCKSIZE);
00066         Mash(temp, passphraseLength + saltLength, keyIV, KEYLENGTH+BLOCKSIZE, MASH_ITERATIONS);
00067         memcpy(key, keyIV, KEYLENGTH);
00068         memcpy(IV, keyIV+KEYLENGTH, BLOCKSIZE);
00069 }
00070 
00071 // ********************************************************
00072 
00073 DefaultEncryptor::DefaultEncryptor(const char *passphrase, BufferedTransformation *outQ)
00074         : ProxyFilter(NULL, 0, 0, outQ), m_passphrase((const byte *)passphrase, strlen(passphrase))
00075 {
00076 }
00077 
00078 DefaultEncryptor::DefaultEncryptor(const byte *passphrase, unsigned int passphraseLength, BufferedTransformation *outQ)
00079         : ProxyFilter(NULL, 0, 0, outQ), m_passphrase(passphrase, passphraseLength)
00080 {
00081 }
00082 
00083 void DefaultEncryptor::FirstPut(const byte *)
00084 {
00085         assert(SALTLENGTH <= DefaultHashModule::DIGESTSIZE);
00086         assert(BLOCKSIZE <= DefaultHashModule::DIGESTSIZE);
00087 
00088         SecByteBlock salt(DefaultHashModule::DIGESTSIZE), keyCheck(DefaultHashModule::DIGESTSIZE);
00089         DefaultHashModule hash;
00090 
00091         // use hash(passphrase | time | clock) as salt
00092         hash.Update(m_passphrase, m_passphrase.size);
00093         time_t t=time(0);
00094         hash.Update((byte *)&t, sizeof(t));
00095         clock_t c=clock();
00096         hash.Update((byte *)&c, sizeof(c));
00097         hash.Final(salt);
00098 
00099         // use hash(passphrase | salt) as key check
00100         hash.Update(m_passphrase, m_passphrase.size);
00101         hash.Update(salt, SALTLENGTH);
00102         hash.Final(keyCheck);
00103 
00104         AttachedTransformation()->Put(salt, SALTLENGTH);
00105 
00106         // mash passphrase and salt together into key and IV
00107         SecByteBlock key(KEYLENGTH);
00108         SecByteBlock IV(BLOCKSIZE);
00109         GenerateKeyIV(m_passphrase, m_passphrase.size, salt, SALTLENGTH, key, IV);
00110 
00111         m_cipher.reset(new Default_ECB_Encryption(key));
00112         SetFilter(new CBCPaddedEncryptor(*m_cipher, IV));
00113 
00114         m_filter->Put(keyCheck, BLOCKSIZE);
00115 }
00116 
00117 void DefaultEncryptor::LastPut(const byte *inString, unsigned int length)
00118 {
00119         m_filter->MessageEnd();
00120 }
00121 
00122 // ********************************************************
00123 
00124 DefaultDecryptor::DefaultDecryptor(const char *p, BufferedTransformation *outQ, bool throwException)
00125         : ProxyFilter(NULL, SALTLENGTH+BLOCKSIZE, 0, outQ)
00126         , m_state(WAITING_FOR_KEYCHECK)
00127         , m_passphrase((const byte *)p, strlen(p))
00128         , m_throwException(throwException)
00129 {
00130 }
00131 
00132 DefaultDecryptor::DefaultDecryptor(const byte *passphrase, unsigned int passphraseLength, BufferedTransformation *outQ, bool throwException)
00133         : ProxyFilter(NULL, SALTLENGTH+BLOCKSIZE, 0, outQ)
00134         , m_state(WAITING_FOR_KEYCHECK)
00135         , m_passphrase(passphrase, passphraseLength)
00136         , m_throwException(throwException)
00137 {
00138 }
00139 
00140 void DefaultDecryptor::FirstPut(const byte *inString)
00141 {
00142         CheckKey(inString, inString+SALTLENGTH);
00143 }
00144 
00145 void DefaultDecryptor::LastPut(const byte *inString, unsigned int length)
00146 {
00147         m_filter->MessageEnd();
00148         m_state = WAITING_FOR_KEYCHECK;
00149 }
00150 
00151 void DefaultDecryptor::CheckKey(const byte *salt, const byte *keyCheck)
00152 {
00153         SecByteBlock check(STDMAX((unsigned int)2*BLOCKSIZE, (unsigned int)DefaultHashModule::DIGESTSIZE));
00154 
00155         DefaultHashModule hash;
00156         hash.Update(m_passphrase, m_passphrase.size);
00157         hash.Update(salt, SALTLENGTH);
00158         hash.Final(check);
00159 
00160         SecByteBlock key(KEYLENGTH);
00161         SecByteBlock IV(BLOCKSIZE);
00162         GenerateKeyIV(m_passphrase, m_passphrase.size, salt, SALTLENGTH, key, IV);
00163 
00164         m_cipher.reset(new Default_ECB_Decryption(key));
00165         std::auto_ptr<CBCPaddedDecryptor> decryptor(new CBCPaddedDecryptor(*m_cipher, IV));
00166 
00167         decryptor->Put(keyCheck, BLOCKSIZE);
00168         decryptor->ForceNextPut();
00169         decryptor->Get(check+BLOCKSIZE, BLOCKSIZE);
00170 
00171         SetFilter(decryptor.release());
00172 
00173         if (memcmp(check, check+BLOCKSIZE, BLOCKSIZE))
00174         {
00175                 m_state = KEY_BAD;
00176                 if (m_throwException)
00177                         throw KeyBadErr();
00178         }
00179         else
00180                 m_state = KEY_GOOD;
00181 }
00182 
00183 // ********************************************************
00184 
00185 static DefaultMAC * NewDefaultEncryptorMAC(const byte *passphrase, unsigned int passphraseLength)
00186 {
00187         unsigned int macKeyLength = DefaultMAC::KeyLength(16);
00188         SecByteBlock macKey(macKeyLength);
00189         // since the MAC is encrypted there is no reason to mash the passphrase for many iterations
00190         Mash(passphrase, passphraseLength, macKey, macKeyLength, 1);
00191         return new DefaultMAC(macKey, macKeyLength);
00192 }
00193 
00194 DefaultEncryptorWithMAC::DefaultEncryptorWithMAC(const char *passphrase, BufferedTransformation *outQueue)
00195         : ProxyFilter(NULL, 0, 0, outQueue)
00196         , m_mac(NewDefaultEncryptorMAC((const byte *)passphrase, strlen(passphrase)))
00197 {
00198         SetFilter(new HashFilter(*m_mac, new DefaultEncryptor(passphrase), true));
00199 }
00200 
00201 DefaultEncryptorWithMAC::DefaultEncryptorWithMAC(const byte *passphrase, unsigned int passphraseLength, BufferedTransformation *outQueue)
00202         : ProxyFilter(NULL, 0, 0, outQueue)
00203         , m_mac(NewDefaultEncryptorMAC(passphrase, passphraseLength))
00204 {
00205         SetFilter(new HashFilter(*m_mac, new DefaultEncryptor(passphrase, passphraseLength), true));
00206 }
00207 
00208 void DefaultEncryptorWithMAC::LastPut(const byte *inString, unsigned int length)
00209 {
00210         m_filter->MessageEnd();
00211 }
00212 
00213 // ********************************************************
00214 
00215 DefaultDecryptorWithMAC::DefaultDecryptorWithMAC(const char *passphrase, BufferedTransformation *outQueue, bool throwException)
00216         : ProxyFilter(NULL, 0, 0, outQueue)
00217         , m_mac(NewDefaultEncryptorMAC((const byte *)passphrase, strlen(passphrase)))
00218         , m_throwException(throwException)
00219 {
00220         SetFilter(new DefaultDecryptor(passphrase, m_hashVerifier=new HashVerifier(*m_mac, NULL, HashVerifier::PUT_MESSAGE), throwException));
00221 }
00222 
00223 DefaultDecryptorWithMAC::DefaultDecryptorWithMAC(const byte *passphrase, unsigned int passphraseLength, BufferedTransformation *outQueue, bool throwException)
00224         : ProxyFilter(NULL, 0, 0, outQueue)
00225         , m_mac(NewDefaultEncryptorMAC(passphrase, passphraseLength))
00226         , m_throwException(throwException)
00227 {
00228         SetFilter(new DefaultDecryptor(passphrase, passphraseLength, m_hashVerifier=new HashVerifier(*m_mac, NULL, HashVerifier::PUT_MESSAGE), throwException));
00229 }
00230 
00231 DefaultDecryptor::State DefaultDecryptorWithMAC::CurrentState() const
00232 {
00233         return static_cast<const DefaultDecryptor *>(m_filter.get())->CurrentState();
00234 }
00235 
00236 bool DefaultDecryptorWithMAC::CheckLastMAC() const
00237 {
00238         return m_hashVerifier->GetLastResult();
00239 }
00240 
00241 void DefaultDecryptorWithMAC::LastPut(const byte *inString, unsigned int length)
00242 {
00243         m_filter->MessageEnd();
00244         if (m_throwException && !CheckLastMAC())
00245                 throw MACBadErr();
00246 }
00247 
00248 NAMESPACE_END

Generated at Mon Jan 15 01:16:30 2001 for Crypto++ by doxygen1.2.4 written by Dimitri van Heesch, © 1997-2000