Crypto++  5.6.3
Free C++ class library of cryptographic schemes
default.cpp
1 // default.cpp - written and placed in the public domain by Wei Dai
2 
3 #include "pch.h"
4 #include "config.h"
5 
6 #if CRYPTOPP_MSC_VERSION
7 # pragma warning(disable: 4127 4189)
8 #endif
9 
10 #include "cryptlib.h"
11 #include "filters.h"
12 #include "smartptr.h"
13 #include "default.h"
14 #include "queue.h"
15 
16 #include <time.h>
17 #include <memory>
18 
19 NAMESPACE_BEGIN(CryptoPP)
20 
21 static const unsigned int MASH_ITERATIONS = 200;
22 static const unsigned int SALTLENGTH = 8;
23 static const unsigned int BLOCKSIZE = DefaultBlockCipher::Encryption::BLOCKSIZE;
24 static const unsigned int KEYLENGTH = DefaultBlockCipher::Encryption::DEFAULT_KEYLENGTH;
25 
26 // The purpose of this function Mash() is to take an arbitrary length input
27 // string and *deterministicly* produce an arbitrary length output string such
28 // that (1) it looks random, (2) no information about the input is
29 // deducible from it, and (3) it contains as much entropy as it can hold, or
30 // the amount of entropy in the input string, whichever is smaller.
31 
32 static void Mash(const byte *in, size_t inLen, byte *out, size_t outLen, int iterations)
33 {
34  if (BytePrecision(outLen) > 2)
35  throw InvalidArgument("Mash: output legnth too large");
36 
37  size_t bufSize = RoundUpToMultipleOf(outLen, (size_t)DefaultHashModule::DIGESTSIZE);
38  byte b[2];
39  SecByteBlock buf(bufSize);
40  SecByteBlock outBuf(bufSize);
41  DefaultHashModule hash;
42 
43  unsigned int i;
44  for(i=0; i<outLen; i+=DefaultHashModule::DIGESTSIZE)
45  {
46  b[0] = (byte) (i >> 8);
47  b[1] = (byte) i;
48  hash.Update(b, 2);
49  hash.Update(in, inLen);
50  hash.Final(outBuf+i);
51  }
52 
53  while (iterations-- > 1)
54  {
55  memcpy(buf, outBuf, bufSize);
56  for (i=0; i<bufSize; i+=DefaultHashModule::DIGESTSIZE)
57  {
58  b[0] = (byte) (i >> 8);
59  b[1] = (byte) i;
60  hash.Update(b, 2);
61  hash.Update(buf, bufSize);
62  hash.Final(outBuf+i);
63  }
64  }
65 
66  memcpy(out, outBuf, outLen);
67 }
68 
69 static void GenerateKeyIV(const byte *passphrase, size_t passphraseLength, const byte *salt, size_t saltLength, byte *key, byte *IV)
70 {
71  SecByteBlock temp(passphraseLength+saltLength);
72  memcpy(temp, passphrase, passphraseLength);
73  memcpy(temp+passphraseLength, salt, saltLength);
74  SecByteBlock keyIV(KEYLENGTH+BLOCKSIZE);
75  Mash(temp, passphraseLength + saltLength, keyIV, KEYLENGTH+BLOCKSIZE, MASH_ITERATIONS);
76  memcpy(key, keyIV, KEYLENGTH);
77  memcpy(IV, keyIV+KEYLENGTH, BLOCKSIZE);
78 }
79 
80 // ********************************************************
81 
82 DefaultEncryptor::DefaultEncryptor(const char *passphrase, BufferedTransformation *attachment)
83  : ProxyFilter(NULL, 0, 0, attachment), m_passphrase((const byte *)passphrase, strlen(passphrase))
84 {
85 }
86 
87 DefaultEncryptor::DefaultEncryptor(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment)
88  : ProxyFilter(NULL, 0, 0, attachment), m_passphrase(passphrase, passphraseLength)
89 {
90 }
91 
92 
93 void DefaultEncryptor::FirstPut(const byte *)
94 {
95  // VC60 workaround: __LINE__ expansion bug
96  CRYPTOPP_COMPILE_ASSERT_INSTANCE(SALTLENGTH <= DefaultHashModule::DIGESTSIZE, 1);
97  CRYPTOPP_COMPILE_ASSERT_INSTANCE(BLOCKSIZE <= DefaultHashModule::DIGESTSIZE, 2);
98 
99  SecByteBlock salt(DefaultHashModule::DIGESTSIZE), keyCheck(DefaultHashModule::DIGESTSIZE);
100  DefaultHashModule hash;
101 
102  // use hash(passphrase | time | clock) as salt
103  hash.Update(m_passphrase, m_passphrase.size());
104  time_t t=time(0);
105  hash.Update((byte *)&t, sizeof(t));
106  clock_t c=clock();
107  hash.Update((byte *)&c, sizeof(c));
108  hash.Final(salt);
109 
110  // use hash(passphrase | salt) as key check
111  hash.Update(m_passphrase, m_passphrase.size());
112  hash.Update(salt, SALTLENGTH);
113  hash.Final(keyCheck);
114 
115  AttachedTransformation()->Put(salt, SALTLENGTH);
116 
117  // mash passphrase and salt together into key and IV
118  SecByteBlock key(KEYLENGTH);
119  SecByteBlock IV(BLOCKSIZE);
120  GenerateKeyIV(m_passphrase, m_passphrase.size(), salt, SALTLENGTH, key, IV);
121 
122  m_cipher.SetKeyWithIV(key, key.size(), IV);
123  SetFilter(new StreamTransformationFilter(m_cipher));
124 
125  m_filter->Put(keyCheck, BLOCKSIZE);
126 }
127 
128 void DefaultEncryptor::LastPut(const byte *inString, size_t length)
129 {
130  CRYPTOPP_UNUSED(inString); CRYPTOPP_UNUSED(length);
131  m_filter->MessageEnd();
132 }
133 
134 // ********************************************************
135 
136 DefaultDecryptor::DefaultDecryptor(const char *p, BufferedTransformation *attachment, bool throwException)
137  : ProxyFilter(NULL, SALTLENGTH+BLOCKSIZE, 0, attachment)
138  , m_state(WAITING_FOR_KEYCHECK)
139  , m_passphrase((const byte *)p, strlen(p))
140  , m_throwException(throwException)
141 {
142 }
143 
144 DefaultDecryptor::DefaultDecryptor(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment, bool throwException)
145  : ProxyFilter(NULL, SALTLENGTH+BLOCKSIZE, 0, attachment)
146  , m_state(WAITING_FOR_KEYCHECK)
147  , m_passphrase(passphrase, passphraseLength)
148  , m_throwException(throwException)
149 {
150 }
151 
152 void DefaultDecryptor::FirstPut(const byte *inString)
153 {
154  CheckKey(inString, inString+SALTLENGTH);
155 }
156 
157 void DefaultDecryptor::LastPut(const byte *inString, size_t length)
158 {
159  CRYPTOPP_UNUSED(inString); CRYPTOPP_UNUSED(length);
160  if (m_filter.get() == NULL)
161  {
162  m_state = KEY_BAD;
163  if (m_throwException)
164  throw KeyBadErr();
165  }
166  else
167  {
168  m_filter->MessageEnd();
169  m_state = WAITING_FOR_KEYCHECK;
170  }
171 }
172 
173 void DefaultDecryptor::CheckKey(const byte *salt, const byte *keyCheck)
174 {
175  SecByteBlock check(STDMAX((unsigned int)2*BLOCKSIZE, (unsigned int)DefaultHashModule::DIGESTSIZE));
176 
177  DefaultHashModule hash;
178  hash.Update(m_passphrase, m_passphrase.size());
179  hash.Update(salt, SALTLENGTH);
180  hash.Final(check);
181 
182  SecByteBlock key(KEYLENGTH);
183  SecByteBlock IV(BLOCKSIZE);
184  GenerateKeyIV(m_passphrase, m_passphrase.size(), salt, SALTLENGTH, key, IV);
185 
186  m_cipher.SetKeyWithIV(key, key.size(), IV);
188 
189  decryptor->Put(keyCheck, BLOCKSIZE);
190  decryptor->ForceNextPut();
191  decryptor->Get(check+BLOCKSIZE, BLOCKSIZE);
192 
193  SetFilter(decryptor.release());
194 
195  if (!VerifyBufsEqual(check, check+BLOCKSIZE, BLOCKSIZE))
196  {
197  m_state = KEY_BAD;
198  if (m_throwException)
199  throw KeyBadErr();
200  }
201  else
202  m_state = KEY_GOOD;
203 }
204 
205 // ********************************************************
206 
207 static DefaultMAC * NewDefaultEncryptorMAC(const byte *passphrase, size_t passphraseLength)
208 {
209  size_t macKeyLength = DefaultMAC::StaticGetValidKeyLength(16);
210  SecByteBlock macKey(macKeyLength);
211  // since the MAC is encrypted there is no reason to mash the passphrase for many iterations
212  Mash(passphrase, passphraseLength, macKey, macKeyLength, 1);
213  return new DefaultMAC(macKey, macKeyLength);
214 }
215 
217  : ProxyFilter(NULL, 0, 0, attachment)
218  , m_mac(NewDefaultEncryptorMAC((const byte *)passphrase, strlen(passphrase)))
219 {
220  SetFilter(new HashFilter(*m_mac, new DefaultEncryptor(passphrase), true));
221 }
222 
223 DefaultEncryptorWithMAC::DefaultEncryptorWithMAC(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment)
224  : ProxyFilter(NULL, 0, 0, attachment)
225  , m_mac(NewDefaultEncryptorMAC(passphrase, passphraseLength))
226 {
227  SetFilter(new HashFilter(*m_mac, new DefaultEncryptor(passphrase, passphraseLength), true));
228 }
229 
230 void DefaultEncryptorWithMAC::LastPut(const byte *inString, size_t length)
231 {
232  CRYPTOPP_UNUSED(inString); CRYPTOPP_UNUSED(length);
233  m_filter->MessageEnd();
234 }
235 
236 // ********************************************************
237 
238 DefaultDecryptorWithMAC::DefaultDecryptorWithMAC(const char *passphrase, BufferedTransformation *attachment, bool throwException)
239  : ProxyFilter(NULL, 0, 0, attachment)
240  , m_mac(NewDefaultEncryptorMAC((const byte *)passphrase, strlen(passphrase)))
241  , m_throwException(throwException)
242 {
243  SetFilter(new DefaultDecryptor(passphrase, m_hashVerifier=new HashVerifier(*m_mac, NULL, HashVerifier::PUT_MESSAGE), throwException));
244 }
245 
246 DefaultDecryptorWithMAC::DefaultDecryptorWithMAC(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment, bool throwException)
247  : ProxyFilter(NULL, 0, 0, attachment)
248  , m_mac(NewDefaultEncryptorMAC(passphrase, passphraseLength))
249  , m_throwException(throwException)
250 {
251  SetFilter(new DefaultDecryptor(passphrase, passphraseLength, m_hashVerifier=new HashVerifier(*m_mac, NULL, HashVerifier::PUT_MESSAGE), throwException));
252 }
253 
254 DefaultDecryptor::State DefaultDecryptorWithMAC::CurrentState() const
255 {
256  return static_cast<const DefaultDecryptor *>(m_filter.get())->CurrentState();
257 }
258 
259 bool DefaultDecryptorWithMAC::CheckLastMAC() const
260 {
261  return m_hashVerifier->GetLastResult();
262 }
263 
264 void DefaultDecryptorWithMAC::LastPut(const byte *inString, size_t length)
265 {
266  CRYPTOPP_UNUSED(inString); CRYPTOPP_UNUSED(length);
267  m_filter->MessageEnd();
268  if (m_throwException && !CheckLastMAC())
269  throw MACBadErr();
270 }
271 
272 NAMESPACE_END
273 
An invalid argument was detected.
Definition: cryptlib.h:182
Base class for Filter classes that are proxies for a chain of other filters.
Definition: filters.h:885
Password-Based Encryptor using TripleDES.
Definition: default.h:29
unsigned int BytePrecision(const T &value)
Returns the number of 8-bit bytes or octets required for a value.
Definition: misc.h:606
Abstract base classes that provide a uniform interface to this library.
size_type size() const
Provides the count of elements in the SecBlock.
Definition: secblock.h:521
Classes for automatic resource management.
Classes for DefaultEncryptor, DefaultDecryptor, DefaultEncryptorWithMAC and DefaultDecryptorWithMAC.
Library configuration file.
SecBlock typedef.
Definition: secblock.h:728
static size_t StaticGetValidKeyLength(size_t keylength)
Provides a valid key length for the algorithm provided by a static function.
Definition: seckey.h:195
Interface for buffered transformations.
Definition: cryptlib.h:1352
Password-Based Decryptor using TripleDES.
Definition: default.h:63
Pointer that overloads operator ->
Definition: smartptr.h:39
DefaultDecryptor(const char *passphrase, BufferedTransformation *attachment=NULL, bool throwException=true)
Constructs a DefaultDecryptor.
Definition: default.cpp:136
HMAC< DefaultHashModule > DefaultMAC
Default HMAC for use withDefaultEncryptorWithMAC and DefaultDecryptorWithMAC.
Definition: default.h:23
Classes for an unlimited queue to store bytes.
Filter wrapper for HashTransformation.
Definition: filters.h:535
Filter wrapper for HashTransformation.
Definition: filters.h:508
size_t Put(byte inByte, bool blocking=true)
Input a byte for processing.
Definition: cryptlib.h:1378
BufferedTransformation * AttachedTransformation()
Retrieve attached transformation.
Definition: filters.cpp:36
Indicates the message should be passed to an attached transformation.
Definition: filters.h:556
2-key TripleDES block cipher
Definition: des.h:71
SHA-1
Definition: sha.h:21
Implementation of BufferedTransformation's attachment interface.
const char * IV()
ConstByteArrayParameter, also accepts const byte * for backwards compatibility.
Definition: argnames.h:21
Filter wrapper for StreamTransformation.
Definition: filters.h:476
HMAC.
Definition: hmac.h:50
DefaultEncryptor(const char *passphrase, BufferedTransformation *attachment=NULL)
Construct a DefaultEncryptor.
Definition: default.cpp:82
bool VerifyBufsEqual(const byte *buf1, const byte *buf2, size_t count)
Performs a near constant-time comparison of two equally sized buffers.
Definition: misc.cpp:96
T1 RoundUpToMultipleOf(const T1 &n, const T2 &m)
Rounds a value up to a multiple of a second value.
Definition: misc.h:846
const T & STDMAX(const T &a, const T &b)
Replacement function for std::max.
Definition: misc.h:460
Crypto++ library namespace.
virtual void Final(byte *digest)
Computes the hash of the current message.
Definition: cryptlib.h:954
void SetFilter(Filter *filter)
Sets the OutputProxy filter.
Definition: filters.cpp:503
DefaultDecryptorWithMAC(const char *passphrase, BufferedTransformation *attachment=NULL, bool throwException=true)
Constructs a DefaultDecryptor.
Definition: default.cpp:238
DefaultEncryptorWithMAC(const char *passphrase, BufferedTransformation *attachment=NULL)
Constructs a DefaultEncryptorWithMAC.
Definition: default.cpp:216