Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Class 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

Generated on Wed Jul 21 19:15:22 2004 for Crypto++ by doxygen 1.3.7-20040704