<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1"> <title>Crypto++: default.cpp Source File</title> <link href="doxygen.css" rel="stylesheet" type="text/css"> </head><body> <!-- Generated by Doxygen 1.3.7 --> <div class="qindex"><a class="qindex" href="index.html">Main Page</a> | <a class="qindex" href="namespaces.html">Namespace List</a> | <a class="qindex" href="hierarchy.html">Class Hierarchy</a> | <a class="qindex" href="classes.html">Alphabetical List</a> | <a class="qindex" href="annotated.html">Class List</a> | <a class="qindex" href="files.html">File List</a> | <a class="qindex" href="namespacemembers.html">Namespace Members</a> | <a class="qindex" href="functions.html">Class Members</a> | <a class="qindex" href="globals.html">File Members</a></div> <h1>default.cpp</h1><pre class="fragment"><div>00001 <span class="comment">// default.cpp - written and placed in the public domain by Wei Dai</span> 00002 00003 <span class="preprocessor">#include "pch.h"</span> 00004 <span class="preprocessor">#include "default.h"</span> 00005 <span class="preprocessor">#include "queue.h"</span> 00006 <span class="preprocessor">#include <time.h></span> 00007 <span class="preprocessor">#include <memory></span> 00008 00009 NAMESPACE_BEGIN(CryptoPP) 00010 00011 static const <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> MASH_ITERATIONS = 200; 00012 static const <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> SALTLENGTH = 8; 00013 static const <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> BLOCKSIZE = <a class="code" href="class_d_e_s___e_d_e2.html">Default_BlockCipher</a>::Encryption::BLOCKSIZE; 00014 static const <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> KEYLENGTH = <a class="code" href="class_d_e_s___e_d_e2.html">Default_BlockCipher</a>::Encryption::DEFAULT_KEYLENGTH; 00015 00016 <span class="comment">// The purpose of this function Mash() is to take an arbitrary length input</span> 00017 <span class="comment">// string and *deterministicly* produce an arbitrary length output string such</span> 00018 <span class="comment">// that (1) it looks random, (2) no information about the input is</span> 00019 <span class="comment">// deducible from it, and (3) it contains as much entropy as it can hold, or</span> 00020 <span class="comment">// the amount of entropy in the input string, whichever is smaller.</span> 00021 00022 static <span class="keywordtype">void</span> Mash(const byte *in, word16 inLen, byte *out, word16 outLen, <span class="keywordtype">int</span> iterations) 00023 { 00024 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> bufSize = (outLen-1+DefaultHashModule::DIGESTSIZE-((outLen-1)%DefaultHashModule::DIGESTSIZE)); 00025 00026 <span class="comment">// ASSERT: bufSize == (the smallest multiple of DIGESTSIZE that is >= outLen)</span> 00027 00028 byte b[2]; 00029 <a class="code" href="class_sec_block.html">SecByteBlock</a> buf(bufSize); 00030 <a class="code" href="class_sec_block.html">SecByteBlock</a> outBuf(bufSize); 00031 <a class="code" href="class_s_h_a.html">DefaultHashModule</a> hash; 00032 00033 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> i; 00034 <span class="keywordflow">for</span>(i=0; i<outLen; i+=DefaultHashModule::DIGESTSIZE) 00035 { 00036 b[0] = (byte) i >> 8; 00037 b[1] = (byte) i; 00038 hash.<a class="code" href="class_iterated_hash_base.html#_iterated_hash_base2a4">Update</a>(b, 2); 00039 hash.<a class="code" href="class_iterated_hash_base.html#_iterated_hash_base2a4">Update</a>(in, inLen); 00040 hash.<a class="code" href="class_hash_transformation.html#_x_m_a_c_c___basea7">Final</a>(outBuf+i); 00041 } 00042 00043 <span class="keywordflow">while</span> (iterations-- > 1) 00044 { 00045 memcpy(buf, outBuf, bufSize); 00046 <span class="keywordflow">for</span> (i=0; i<bufSize; i+=DefaultHashModule::DIGESTSIZE) 00047 { 00048 b[0] = (byte) i >> 8; 00049 b[1] = (byte) i; 00050 hash.<a class="code" href="class_iterated_hash_base.html#_iterated_hash_base2a4">Update</a>(b, 2); 00051 hash.<a class="code" href="class_iterated_hash_base.html#_iterated_hash_base2a4">Update</a>(buf, bufSize); 00052 hash.<a class="code" href="class_hash_transformation.html#_x_m_a_c_c___basea7">Final</a>(outBuf+i); 00053 } 00054 } 00055 00056 memcpy(out, outBuf, outLen); 00057 } 00058 00059 <span class="keyword">static</span> <span class="keywordtype">void</span> GenerateKeyIV(<span class="keyword">const</span> byte *passphrase, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> passphraseLength, <span class="keyword">const</span> byte *salt, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> saltLength, byte *key, byte *IV) 00060 { 00061 <a class="code" href="class_sec_block.html">SecByteBlock</a> temp(passphraseLength+saltLength); 00062 memcpy(temp, passphrase, passphraseLength); 00063 memcpy(temp+passphraseLength, salt, saltLength); 00064 <a class="code" href="class_sec_block.html">SecByteBlock</a> 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 <span class="comment">// ********************************************************</span> 00071 00072 DefaultEncryptor::DefaultEncryptor(<span class="keyword">const</span> <span class="keywordtype">char</span> *passphrase, <a class="code" href="class_buffered_transformation.html">BufferedTransformation</a> *attachment) 00073 : <a class="code" href="class_proxy_filter.html">ProxyFilter</a>(NULL, 0, 0, attachment), m_passphrase((const byte *)passphrase, strlen(passphrase)) 00074 { 00075 } 00076 00077 DefaultEncryptor::DefaultEncryptor(<span class="keyword">const</span> byte *passphrase, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> passphraseLength, <a class="code" href="class_buffered_transformation.html">BufferedTransformation</a> *attachment) 00078 : <a class="code" href="class_proxy_filter.html">ProxyFilter</a>(NULL, 0, 0, attachment), m_passphrase(passphrase, passphraseLength) 00079 { 00080 } 00081 00082 00083 <span class="keywordtype">void</span> DefaultEncryptor::FirstPut(<span class="keyword">const</span> byte *) 00084 { 00085 <span class="comment">// VC60 workaround: __LINE__ expansion bug</span> 00086 CRYPTOPP_COMPILE_ASSERT_INSTANCE(SALTLENGTH <= DefaultHashModule::DIGESTSIZE, 1); 00087 CRYPTOPP_COMPILE_ASSERT_INSTANCE(BLOCKSIZE <= DefaultHashModule::DIGESTSIZE, 2); 00088 00089 <a class="code" href="class_sec_block.html">SecByteBlock</a> salt(DefaultHashModule::DIGESTSIZE), keyCheck(DefaultHashModule::DIGESTSIZE); 00090 <a class="code" href="class_s_h_a.html">DefaultHashModule</a> hash; 00091 00092 <span class="comment">// use hash(passphrase | time | clock) as salt</span> 00093 hash.<a class="code" href="class_iterated_hash_base.html#_iterated_hash_base2a4">Update</a>(m_passphrase, m_passphrase.<a class="code" href="class_sec_block.html#_sec_block_with_hinta15">size</a>()); 00094 time_t t=time(0); 00095 hash.<a class="code" href="class_iterated_hash_base.html#_iterated_hash_base2a4">Update</a>((byte *)&t, <span class="keyword">sizeof</span>(t)); 00096 clock_t c=clock(); 00097 hash.<a class="code" href="class_iterated_hash_base.html#_iterated_hash_base2a4">Update</a>((byte *)&c, <span class="keyword">sizeof</span>(c)); 00098 hash.<a class="code" href="class_hash_transformation.html#_x_m_a_c_c___basea7">Final</a>(salt); 00099 00100 <span class="comment">// use hash(passphrase | salt) as key check</span> 00101 hash.<a class="code" href="class_iterated_hash_base.html#_iterated_hash_base2a4">Update</a>(m_passphrase, m_passphrase.<a class="code" href="class_sec_block.html#_sec_block_with_hinta15">size</a>()); 00102 hash.<a class="code" href="class_iterated_hash_base.html#_iterated_hash_base2a4">Update</a>(salt, SALTLENGTH); 00103 hash.<a class="code" href="class_hash_transformation.html#_x_m_a_c_c___basea7">Final</a>(keyCheck); 00104 00105 <a class="code" href="class_filter.html#_zlib_decompressora8">AttachedTransformation</a>()-><a class="code" href="class_buffered_transformation.html#_zlib_decompressorz1_0">Put</a>(salt, SALTLENGTH); 00106 00107 <span class="comment">// mash passphrase and salt together into key and IV</span> 00108 <a class="code" href="class_sec_block.html">SecByteBlock</a> key(KEYLENGTH); 00109 <a class="code" href="class_sec_block.html">SecByteBlock</a> <a class="code" href="namespace_name.html#a4">IV</a>(BLOCKSIZE); 00110 GenerateKeyIV(m_passphrase, m_passphrase.<a class="code" href="class_sec_block.html#_sec_block_with_hinta15">size</a>(), salt, SALTLENGTH, key, <a class="code" href="namespace_name.html#a4">IV</a>); 00111 00112 m_cipher.SetKeyWithIV(key, key.size(), <a class="code" href="namespace_name.html#a4">IV</a>); 00113 SetFilter(<span class="keyword">new</span> <a class="code" href="class_stream_transformation_filter.html">StreamTransformationFilter</a>(m_cipher)); 00114 00115 m_filter->Put(keyCheck, BLOCKSIZE); 00116 } 00117 00118 <span class="keywordtype">void</span> DefaultEncryptor::LastPut(<span class="keyword">const</span> byte *inString, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> length) 00119 { 00120 m_filter->MessageEnd(); 00121 } 00122 00123 <span class="comment">// ********************************************************</span> 00124 00125 DefaultDecryptor::DefaultDecryptor(<span class="keyword">const</span> <span class="keywordtype">char</span> *p, <a class="code" href="class_buffered_transformation.html">BufferedTransformation</a> *attachment, <span class="keywordtype">bool</span> throwException) 00126 : <a class="code" href="class_proxy_filter.html">ProxyFilter</a>(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(<span class="keyword">const</span> byte *passphrase, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> passphraseLength, <a class="code" href="class_buffered_transformation.html">BufferedTransformation</a> *attachment, <span class="keywordtype">bool</span> throwException) 00134 : <a class="code" href="class_proxy_filter.html">ProxyFilter</a>(NULL, SALTLENGTH+BLOCKSIZE, 0, attachment) 00135 , m_state(WAITING_FOR_KEYCHECK) 00136 , m_passphrase(passphrase, passphraseLength) 00137 , m_throwException(throwException) 00138 { 00139 } 00140 00141 <span class="keywordtype">void</span> DefaultDecryptor::FirstPut(<span class="keyword">const</span> byte *inString) 00142 { 00143 CheckKey(inString, inString+SALTLENGTH); 00144 } 00145 00146 <span class="keywordtype">void</span> DefaultDecryptor::LastPut(<span class="keyword">const</span> byte *inString, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> length) 00147 { 00148 <span class="keywordflow">if</span> (m_filter.get() == NULL) 00149 { 00150 m_state = KEY_BAD; 00151 <span class="keywordflow">if</span> (m_throwException) 00152 <span class="keywordflow">throw</span> KeyBadErr(); 00153 } 00154 <span class="keywordflow">else</span> 00155 { 00156 m_filter->MessageEnd(); 00157 m_state = WAITING_FOR_KEYCHECK; 00158 } 00159 } 00160 00161 <span class="keywordtype">void</span> DefaultDecryptor::CheckKey(<span class="keyword">const</span> byte *salt, <span class="keyword">const</span> byte *keyCheck) 00162 { 00163 <a class="code" href="class_sec_block.html">SecByteBlock</a> check(STDMAX((<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span>)2*BLOCKSIZE, (<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span>)DefaultHashModule::DIGESTSIZE)); 00164 00165 <a class="code" href="class_s_h_a.html">DefaultHashModule</a> hash; 00166 hash.<a class="code" href="class_iterated_hash_base.html#_iterated_hash_base2a4">Update</a>(m_passphrase, m_passphrase.<a class="code" href="class_sec_block.html#_sec_block_with_hinta15">size</a>()); 00167 hash.<a class="code" href="class_iterated_hash_base.html#_iterated_hash_base2a4">Update</a>(salt, SALTLENGTH); 00168 hash.<a class="code" href="class_hash_transformation.html#_x_m_a_c_c___basea7">Final</a>(check); 00169 00170 <a class="code" href="class_sec_block.html">SecByteBlock</a> key(KEYLENGTH); 00171 <a class="code" href="class_sec_block.html">SecByteBlock</a> <a class="code" href="namespace_name.html#a4">IV</a>(BLOCKSIZE); 00172 GenerateKeyIV(m_passphrase, m_passphrase.<a class="code" href="class_sec_block.html#_sec_block_with_hinta15">size</a>(), salt, SALTLENGTH, key, <a class="code" href="namespace_name.html#a4">IV</a>); 00173 00174 m_cipher.SetKeyWithIV(key, key.size(), <a class="code" href="namespace_name.html#a4">IV</a>); 00175 std::auto_ptr<StreamTransformationFilter> decryptor(<span class="keyword">new</span> <a class="code" href="class_stream_transformation_filter.html">StreamTransformationFilter</a>(m_cipher)); 00176 00177 decryptor->Put(keyCheck, BLOCKSIZE); 00178 decryptor->ForceNextPut(); 00179 decryptor->Get(check+BLOCKSIZE, BLOCKSIZE); 00180 00181 SetFilter(decryptor.release()); 00182 00183 <span class="keywordflow">if</span> (memcmp(check, check+BLOCKSIZE, BLOCKSIZE)) 00184 { 00185 m_state = KEY_BAD; 00186 <span class="keywordflow">if</span> (m_throwException) 00187 <span class="keywordflow">throw</span> KeyBadErr(); 00188 } 00189 <span class="keywordflow">else</span> 00190 m_state = KEY_GOOD; 00191 } 00192 00193 <span class="comment">// ********************************************************</span> 00194 00195 <span class="keyword">static</span> <a class="code" href="class_h_m_a_c.html">DefaultMAC</a> * NewDefaultEncryptorMAC(<span class="keyword">const</span> byte *passphrase, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> passphraseLength) 00196 { 00197 <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> macKeyLength = DefaultMAC::StaticGetValidKeyLength(16); 00198 <a class="code" href="class_sec_block.html">SecByteBlock</a> macKey(macKeyLength); 00199 <span class="comment">// since the MAC is encrypted there is no reason to mash the passphrase for many iterations</span> 00200 Mash(passphrase, passphraseLength, macKey, macKeyLength, 1); 00201 <span class="keywordflow">return</span> <span class="keyword">new</span> <a class="code" href="class_h_m_a_c.html">DefaultMAC</a>(macKey, macKeyLength); 00202 } 00203 00204 DefaultEncryptorWithMAC::DefaultEncryptorWithMAC(<span class="keyword">const</span> <span class="keywordtype">char</span> *passphrase, <a class="code" href="class_buffered_transformation.html">BufferedTransformation</a> *attachment) 00205 : <a class="code" href="class_proxy_filter.html">ProxyFilter</a>(NULL, 0, 0, attachment) 00206 , m_mac(NewDefaultEncryptorMAC((const byte *)passphrase, strlen(passphrase))) 00207 { 00208 SetFilter(<span class="keyword">new</span> <a class="code" href="class_hash_filter.html">HashFilter</a>(*m_mac, <span class="keyword">new</span> <a class="code" href="class_default_encryptor.html">DefaultEncryptor</a>(passphrase), <span class="keyword">true</span>)); 00209 } 00210 00211 DefaultEncryptorWithMAC::DefaultEncryptorWithMAC(<span class="keyword">const</span> byte *passphrase, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> passphraseLength, <a class="code" href="class_buffered_transformation.html">BufferedTransformation</a> *attachment) 00212 : <a class="code" href="class_proxy_filter.html">ProxyFilter</a>(NULL, 0, 0, attachment) 00213 , m_mac(NewDefaultEncryptorMAC(passphrase, passphraseLength)) 00214 { 00215 SetFilter(<span class="keyword">new</span> <a class="code" href="class_hash_filter.html">HashFilter</a>(*m_mac, <span class="keyword">new</span> <a class="code" href="class_default_encryptor.html">DefaultEncryptor</a>(passphrase, passphraseLength), <span class="keyword">true</span>)); 00216 } 00217 00218 <span class="keywordtype">void</span> DefaultEncryptorWithMAC::LastPut(<span class="keyword">const</span> byte *inString, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> length) 00219 { 00220 m_filter->MessageEnd(); 00221 } 00222 00223 <span class="comment">// ********************************************************</span> 00224 00225 DefaultDecryptorWithMAC::DefaultDecryptorWithMAC(<span class="keyword">const</span> <span class="keywordtype">char</span> *passphrase, <a class="code" href="class_buffered_transformation.html">BufferedTransformation</a> *attachment, <span class="keywordtype">bool</span> throwException) 00226 : <a class="code" href="class_proxy_filter.html">ProxyFilter</a>(NULL, 0, 0, attachment) 00227 , m_mac(NewDefaultEncryptorMAC((const byte *)passphrase, strlen(passphrase))) 00228 , m_throwException(throwException) 00229 { 00230 SetFilter(<span class="keyword">new</span> <a class="code" href="class_default_decryptor.html">DefaultDecryptor</a>(passphrase, m_hashVerifier=<span class="keyword">new</span> <a class="code" href="class_hash_verification_filter.html">HashVerifier</a>(*m_mac, NULL, HashVerifier::PUT_MESSAGE), throwException)); 00231 } 00232 00233 DefaultDecryptorWithMAC::DefaultDecryptorWithMAC(<span class="keyword">const</span> byte *passphrase, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> passphraseLength, <a class="code" href="class_buffered_transformation.html">BufferedTransformation</a> *attachment, <span class="keywordtype">bool</span> throwException) 00234 : <a class="code" href="class_proxy_filter.html">ProxyFilter</a>(NULL, 0, 0, attachment) 00235 , m_mac(NewDefaultEncryptorMAC(passphrase, passphraseLength)) 00236 , m_throwException(throwException) 00237 { 00238 SetFilter(<span class="keyword">new</span> <a class="code" href="class_default_decryptor.html">DefaultDecryptor</a>(passphrase, passphraseLength, m_hashVerifier=<span class="keyword">new</span> <a class="code" href="class_hash_verification_filter.html">HashVerifier</a>(*m_mac, NULL, HashVerifier::PUT_MESSAGE), throwException)); 00239 } 00240 00241 DefaultDecryptor::State DefaultDecryptorWithMAC::CurrentState()<span class="keyword"> const</span> 00242 <span class="keyword"></span>{ 00243 <span class="keywordflow">return</span> static_cast<const DefaultDecryptor *>(m_filter.get())->CurrentState(); 00244 } 00245 00246 <span class="keywordtype">bool</span> DefaultDecryptorWithMAC::CheckLastMAC()<span class="keyword"> const</span> 00247 <span class="keyword"></span>{ 00248 <span class="keywordflow">return</span> m_hashVerifier-><a class="code" href="class_hash_verification_filter.html#_hash_verification_filtera1">GetLastResult</a>(); 00249 } 00250 00251 <span class="keywordtype">void</span> DefaultDecryptorWithMAC::LastPut(<span class="keyword">const</span> byte *inString, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> length) 00252 { 00253 m_filter->MessageEnd(); 00254 <span class="keywordflow">if</span> (m_throwException && !CheckLastMAC()) 00255 <span class="keywordflow">throw</span> MACBadErr(); 00256 } 00257 00258 NAMESPACE_END </div></pre><hr size="1"><address style="align: right;"><small>Generated on Sun Nov 7 08:23:57 2004 for Crypto++ by <a href="http://www.doxygen.org/index.html"> <img src="doxygen.png" alt="doxygen" align="middle" border=0 ></a> 1.3.7 </small></address> </body> </html>