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