1
// default.cpp - written and placed in the public domain by Wei Dai
9
NAMESPACE_BEGIN(CryptoPP)
11
static const unsigned int MASH_ITERATIONS = 200;
12
static const unsigned int SALTLENGTH = 8;
13
static const unsigned int BLOCKSIZE = Default_BlockCipher::Encryption::BLOCKSIZE;
14
static const unsigned int KEYLENGTH = Default_BlockCipher::Encryption::DEFAULT_KEYLENGTH;
16
// The purpose of this function Mash() is to take an arbitrary length input
17
// string and *deterministicly* produce an arbitrary length output string such
18
// that (1) it looks random, (2) no information about the input is
19
// deducible from it, and (3) it contains as much entropy as it can hold, or
20
// the amount of entropy in the input string, whichever is smaller.
22
static void Mash(const byte *in, size_t inLen, byte *out, size_t outLen, int iterations)
24
if (BytePrecision(outLen) > 2)
25
throw InvalidArgument("Mash: output legnth too large");
27
size_t bufSize = RoundUpToMultipleOf(outLen, (size_t)DefaultHashModule::DIGESTSIZE);
29
SecByteBlock buf(bufSize);
30
SecByteBlock outBuf(bufSize);
31
DefaultHashModule hash;
34
for(i=0; i<outLen; i+=DefaultHashModule::DIGESTSIZE)
36
b[0] = (byte) (i >> 8);
39
hash.Update(in, inLen);
43
while (iterations-- > 1)
45
memcpy(buf, outBuf, bufSize);
46
for (i=0; i<bufSize; i+=DefaultHashModule::DIGESTSIZE)
48
b[0] = (byte) (i >> 8);
51
hash.Update(buf, bufSize);
56
memcpy(out, outBuf, outLen);
59
static void GenerateKeyIV(const byte *passphrase, size_t passphraseLength, const byte *salt, size_t saltLength, byte *key, byte *IV)
61
SecByteBlock temp(passphraseLength+saltLength);
62
memcpy(temp, passphrase, passphraseLength);
63
memcpy(temp+passphraseLength, salt, saltLength);
64
SecByteBlock keyIV(KEYLENGTH+BLOCKSIZE);
65
Mash(temp, passphraseLength + saltLength, keyIV, KEYLENGTH+BLOCKSIZE, MASH_ITERATIONS);
66
memcpy(key, keyIV, KEYLENGTH);
67
memcpy(IV, keyIV+KEYLENGTH, BLOCKSIZE);
70
// ********************************************************
72
DefaultEncryptor::DefaultEncryptor(const char *passphrase, BufferedTransformation *attachment)
73
: ProxyFilter(NULL, 0, 0, attachment), m_passphrase((const byte *)passphrase, strlen(passphrase))
77
DefaultEncryptor::DefaultEncryptor(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment)
78
: ProxyFilter(NULL, 0, 0, attachment), m_passphrase(passphrase, passphraseLength)
83
void DefaultEncryptor::FirstPut(const byte *)
85
// VC60 workaround: __LINE__ expansion bug
86
CRYPTOPP_COMPILE_ASSERT_INSTANCE(SALTLENGTH <= DefaultHashModule::DIGESTSIZE, 1);
87
CRYPTOPP_COMPILE_ASSERT_INSTANCE(BLOCKSIZE <= DefaultHashModule::DIGESTSIZE, 2);
89
SecByteBlock salt(DefaultHashModule::DIGESTSIZE), keyCheck(DefaultHashModule::DIGESTSIZE);
90
DefaultHashModule hash;
92
// use hash(passphrase | time | clock) as salt
93
hash.Update(m_passphrase, m_passphrase.size());
95
hash.Update((byte *)&t, sizeof(t));
97
hash.Update((byte *)&c, sizeof(c));
100
// use hash(passphrase | salt) as key check
101
hash.Update(m_passphrase, m_passphrase.size());
102
hash.Update(salt, SALTLENGTH);
103
hash.Final(keyCheck);
105
AttachedTransformation()->Put(salt, SALTLENGTH);
107
// mash passphrase and salt together into key and IV
108
SecByteBlock key(KEYLENGTH);
109
SecByteBlock IV(BLOCKSIZE);
110
GenerateKeyIV(m_passphrase, m_passphrase.size(), salt, SALTLENGTH, key, IV);
112
m_cipher.SetKeyWithIV(key, key.size(), IV);
113
SetFilter(new StreamTransformationFilter(m_cipher));
115
m_filter->Put(keyCheck, BLOCKSIZE);
118
void DefaultEncryptor::LastPut(const byte *inString, size_t length)
120
m_filter->MessageEnd();
123
// ********************************************************
125
DefaultDecryptor::DefaultDecryptor(const char *p, BufferedTransformation *attachment, bool throwException)
126
: ProxyFilter(NULL, SALTLENGTH+BLOCKSIZE, 0, attachment)
127
, m_state(WAITING_FOR_KEYCHECK)
128
, m_passphrase((const byte *)p, strlen(p))
129
, m_throwException(throwException)
133
DefaultDecryptor::DefaultDecryptor(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment, bool throwException)
134
: ProxyFilter(NULL, SALTLENGTH+BLOCKSIZE, 0, attachment)
135
, m_state(WAITING_FOR_KEYCHECK)
136
, m_passphrase(passphrase, passphraseLength)
137
, m_throwException(throwException)
141
void DefaultDecryptor::FirstPut(const byte *inString)
143
CheckKey(inString, inString+SALTLENGTH);
146
void DefaultDecryptor::LastPut(const byte *inString, size_t length)
148
if (m_filter.get() == NULL)
151
if (m_throwException)
156
m_filter->MessageEnd();
157
m_state = WAITING_FOR_KEYCHECK;
161
void DefaultDecryptor::CheckKey(const byte *salt, const byte *keyCheck)
163
SecByteBlock check(STDMAX((unsigned int)2*BLOCKSIZE, (unsigned int)DefaultHashModule::DIGESTSIZE));
165
DefaultHashModule hash;
166
hash.Update(m_passphrase, m_passphrase.size());
167
hash.Update(salt, SALTLENGTH);
170
SecByteBlock key(KEYLENGTH);
171
SecByteBlock IV(BLOCKSIZE);
172
GenerateKeyIV(m_passphrase, m_passphrase.size(), salt, SALTLENGTH, key, IV);
174
m_cipher.SetKeyWithIV(key, key.size(), IV);
175
std::auto_ptr<StreamTransformationFilter> decryptor(new StreamTransformationFilter(m_cipher));
177
decryptor->Put(keyCheck, BLOCKSIZE);
178
decryptor->ForceNextPut();
179
decryptor->Get(check+BLOCKSIZE, BLOCKSIZE);
181
SetFilter(decryptor.release());
183
if (!VerifyBufsEqual(check, check+BLOCKSIZE, BLOCKSIZE))
186
if (m_throwException)
193
// ********************************************************
195
static DefaultMAC * NewDefaultEncryptorMAC(const byte *passphrase, size_t passphraseLength)
197
size_t macKeyLength = DefaultMAC::StaticGetValidKeyLength(16);
198
SecByteBlock macKey(macKeyLength);
199
// since the MAC is encrypted there is no reason to mash the passphrase for many iterations
200
Mash(passphrase, passphraseLength, macKey, macKeyLength, 1);
201
return new DefaultMAC(macKey, macKeyLength);
204
DefaultEncryptorWithMAC::DefaultEncryptorWithMAC(const char *passphrase, BufferedTransformation *attachment)
205
: ProxyFilter(NULL, 0, 0, attachment)
206
, m_mac(NewDefaultEncryptorMAC((const byte *)passphrase, strlen(passphrase)))
208
SetFilter(new HashFilter(*m_mac, new DefaultEncryptor(passphrase), true));
211
DefaultEncryptorWithMAC::DefaultEncryptorWithMAC(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment)
212
: ProxyFilter(NULL, 0, 0, attachment)
213
, m_mac(NewDefaultEncryptorMAC(passphrase, passphraseLength))
215
SetFilter(new HashFilter(*m_mac, new DefaultEncryptor(passphrase, passphraseLength), true));
218
void DefaultEncryptorWithMAC::LastPut(const byte *inString, size_t length)
220
m_filter->MessageEnd();
223
// ********************************************************
225
DefaultDecryptorWithMAC::DefaultDecryptorWithMAC(const char *passphrase, BufferedTransformation *attachment, bool throwException)
226
: ProxyFilter(NULL, 0, 0, attachment)
227
, m_mac(NewDefaultEncryptorMAC((const byte *)passphrase, strlen(passphrase)))
228
, m_throwException(throwException)
230
SetFilter(new DefaultDecryptor(passphrase, m_hashVerifier=new HashVerifier(*m_mac, NULL, HashVerifier::PUT_MESSAGE), throwException));
233
DefaultDecryptorWithMAC::DefaultDecryptorWithMAC(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment, bool throwException)
234
: ProxyFilter(NULL, 0, 0, attachment)
235
, m_mac(NewDefaultEncryptorMAC(passphrase, passphraseLength))
236
, m_throwException(throwException)
238
SetFilter(new DefaultDecryptor(passphrase, passphraseLength, m_hashVerifier=new HashVerifier(*m_mac, NULL, HashVerifier::PUT_MESSAGE), throwException));
241
DefaultDecryptor::State DefaultDecryptorWithMAC::CurrentState() const
243
return static_cast<const DefaultDecryptor *>(m_filter.get())->CurrentState();
246
bool DefaultDecryptorWithMAC::CheckLastMAC() const
248
return m_hashVerifier->GetLastResult();
251
void DefaultDecryptorWithMAC::LastPut(const byte *inString, size_t length)
253
m_filter->MessageEnd();
254
if (m_throwException && !CheckLastMAC())