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, size_t inLen, byte *out, size_t outLen, int iterations)
00023 {
00024         if (BytePrecision(outLen) > 2)
00025                 throw InvalidArgument("Mash: output legnth too large");
00026 
00027         size_t bufSize = RoundUpToMultipleOf(outLen, (size_t)DefaultHashModule::DIGESTSIZE);
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, size_t passphraseLength, const byte *salt, size_t 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, size_t 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, size_t 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, size_t 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, size_t 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, size_t passphraseLength)
00196 {
00197         size_t 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, size_t 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, size_t 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, size_t 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, size_t length)
00252 {
00253         m_filter->MessageEnd();
00254         if (m_throwException && !CheckLastMAC())
00255                 throw MACBadErr();
00256 }
00257 
00258 NAMESPACE_END

Generated on Sat Dec 23 02:07:06 2006 for Crypto++ by  doxygen 1.5.1-p1