Crypto++  5.6.5
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 void DefaultEncryptor::FirstPut(const byte *)
93 {
94  CRYPTOPP_COMPILE_ASSERT(SALTLENGTH <= DefaultHashModule::DIGESTSIZE);
95  CRYPTOPP_COMPILE_ASSERT(BLOCKSIZE <= DefaultHashModule::DIGESTSIZE);
96 
97  SecByteBlock salt(DefaultHashModule::DIGESTSIZE), keyCheck(DefaultHashModule::DIGESTSIZE);
98  DefaultHashModule hash;
99 
100  // use hash(passphrase | time | clock) as salt
101  hash.Update(m_passphrase, m_passphrase.size());
102  time_t t=time(0);
103  hash.Update((byte *)&t, sizeof(t));
104  clock_t c=clock();
105  hash.Update((byte *)&c, sizeof(c));
106  hash.Final(salt);
107 
108  // use hash(passphrase | salt) as key check
109  hash.Update(m_passphrase, m_passphrase.size());
110  hash.Update(salt, SALTLENGTH);
111  hash.Final(keyCheck);
112 
113  AttachedTransformation()->Put(salt, SALTLENGTH);
114 
115  // mash passphrase and salt together into key and IV
116  SecByteBlock key(KEYLENGTH);
117  SecByteBlock IV(BLOCKSIZE);
118  GenerateKeyIV(m_passphrase, m_passphrase.size(), salt, SALTLENGTH, key, IV);
119 
120  m_cipher.SetKeyWithIV(key, key.size(), IV);
121  SetFilter(new StreamTransformationFilter(m_cipher));
122 
123  m_filter->Put(keyCheck, BLOCKSIZE);
124 }
125 
126 void DefaultEncryptor::LastPut(const byte *inString, size_t length)
127 {
128  CRYPTOPP_UNUSED(inString); CRYPTOPP_UNUSED(length);
129  m_filter->MessageEnd();
130 }
131 
132 // ********************************************************
133 
134 DefaultDecryptor::DefaultDecryptor(const char *p, BufferedTransformation *attachment, bool throwException)
135  : ProxyFilter(NULL, SALTLENGTH+BLOCKSIZE, 0, attachment)
136  , m_state(WAITING_FOR_KEYCHECK)
137  , m_passphrase((const byte *)p, strlen(p))
138  , m_throwException(throwException)
139 {
140 }
141 
142 DefaultDecryptor::DefaultDecryptor(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment, bool throwException)
143  : ProxyFilter(NULL, SALTLENGTH+BLOCKSIZE, 0, attachment)
144  , m_state(WAITING_FOR_KEYCHECK)
145  , m_passphrase(passphrase, passphraseLength)
146  , m_throwException(throwException)
147 {
148 }
149 
150 void DefaultDecryptor::FirstPut(const byte *inString)
151 {
152  CheckKey(inString, inString+SALTLENGTH);
153 }
154 
155 void DefaultDecryptor::LastPut(const byte *inString, size_t length)
156 {
157  CRYPTOPP_UNUSED(inString); CRYPTOPP_UNUSED(length);
158  if (m_filter.get() == NULL)
159  {
160  m_state = KEY_BAD;
161  if (m_throwException)
162  throw KeyBadErr();
163  }
164  else
165  {
166  m_filter->MessageEnd();
167  m_state = WAITING_FOR_KEYCHECK;
168  }
169 }
170 
171 void DefaultDecryptor::CheckKey(const byte *salt, const byte *keyCheck)
172 {
173  SecByteBlock check(STDMAX((unsigned int)2*BLOCKSIZE, (unsigned int)DefaultHashModule::DIGESTSIZE));
174 
175  DefaultHashModule hash;
176  hash.Update(m_passphrase, m_passphrase.size());
177  hash.Update(salt, SALTLENGTH);
178  hash.Final(check);
179 
180  SecByteBlock key(KEYLENGTH);
181  SecByteBlock IV(BLOCKSIZE);
182  GenerateKeyIV(m_passphrase, m_passphrase.size(), salt, SALTLENGTH, key, IV);
183 
184  m_cipher.SetKeyWithIV(key, key.size(), IV);
186 
187  decryptor->Put(keyCheck, BLOCKSIZE);
188  decryptor->ForceNextPut();
189  decryptor->Get(check+BLOCKSIZE, BLOCKSIZE);
190 
191  SetFilter(decryptor.release());
192 
193  if (!VerifyBufsEqual(check, check+BLOCKSIZE, BLOCKSIZE))
194  {
195  m_state = KEY_BAD;
196  if (m_throwException)
197  throw KeyBadErr();
198  }
199  else
200  m_state = KEY_GOOD;
201 }
202 
203 // ********************************************************
204 
205 static DefaultMAC * NewDefaultEncryptorMAC(const byte *passphrase, size_t passphraseLength)
206 {
207  size_t macKeyLength = DefaultMAC::StaticGetValidKeyLength(16);
208  SecByteBlock macKey(macKeyLength);
209  // since the MAC is encrypted there is no reason to mash the passphrase for many iterations
210  Mash(passphrase, passphraseLength, macKey, macKeyLength, 1);
211  return new DefaultMAC(macKey, macKeyLength);
212 }
213 
215  : ProxyFilter(NULL, 0, 0, attachment)
216  , m_mac(NewDefaultEncryptorMAC((const byte *)passphrase, strlen(passphrase)))
217 {
218  SetFilter(new HashFilter(*m_mac, new DefaultEncryptor(passphrase), true));
219 }
220 
221 DefaultEncryptorWithMAC::DefaultEncryptorWithMAC(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment)
222  : ProxyFilter(NULL, 0, 0, attachment)
223  , m_mac(NewDefaultEncryptorMAC(passphrase, passphraseLength))
224 {
225  SetFilter(new HashFilter(*m_mac, new DefaultEncryptor(passphrase, passphraseLength), true));
226 }
227 
228 void DefaultEncryptorWithMAC::LastPut(const byte *inString, size_t length)
229 {
230  CRYPTOPP_UNUSED(inString); CRYPTOPP_UNUSED(length);
231  m_filter->MessageEnd();
232 }
233 
234 // ********************************************************
235 
236 DefaultDecryptorWithMAC::DefaultDecryptorWithMAC(const char *passphrase, BufferedTransformation *attachment, bool throwException)
237  : ProxyFilter(NULL, 0, 0, attachment)
238  , m_mac(NewDefaultEncryptorMAC((const byte *)passphrase, strlen(passphrase)))
239  , m_throwException(throwException)
240 {
241  SetFilter(new DefaultDecryptor(passphrase, m_hashVerifier=new HashVerificationFilter(*m_mac, NULL, HashVerificationFilter::PUT_MESSAGE), throwException));
242 }
243 
244 DefaultDecryptorWithMAC::DefaultDecryptorWithMAC(const byte *passphrase, size_t passphraseLength, BufferedTransformation *attachment, bool throwException)
245  : ProxyFilter(NULL, 0, 0, attachment)
246  , m_mac(NewDefaultEncryptorMAC(passphrase, passphraseLength))
247  , m_throwException(throwException)
248 {
249  SetFilter(new DefaultDecryptor(passphrase, passphraseLength, m_hashVerifier=new HashVerificationFilter(*m_mac, NULL, HashVerificationFilter::PUT_MESSAGE), throwException));
250 }
251 
252 DefaultDecryptor::State DefaultDecryptorWithMAC::CurrentState() const
253 {
254  return static_cast<const DefaultDecryptor *>(m_filter.get())->CurrentState();
255 }
256 
257 bool DefaultDecryptorWithMAC::CheckLastMAC() const
258 {
259  return m_hashVerifier->GetLastResult();
260 }
261 
262 void DefaultDecryptorWithMAC::LastPut(const byte *inString, size_t length)
263 {
264  CRYPTOPP_UNUSED(inString); CRYPTOPP_UNUSED(length);
265  m_filter->MessageEnd();
266  if (m_throwException && !CheckLastMAC())
267  throw MACBadErr();
268 }
269 
270 NAMESPACE_END
271 
An invalid argument was detected.
Definition: cryptlib.h:184
Base class for Filter classes that are proxies for a chain of other filters.
Definition: filters.h:951
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:632
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:524
Classes for automatic resource management.
Classes for DefaultEncryptor, DefaultDecryptor, DefaultEncryptorWithMAC and DefaultDecryptorWithMAC.
Library configuration file.
void Update(const byte *input, size_t length)
Updates a hash with additional input.
Definition: iterhash.cpp:12
SecBlock typedef.
Definition: secblock.h:731
static size_t StaticGetValidKeyLength(size_t keylength)
Provides a valid key length for the algorithm provided by a static function.
Definition: seckey.h:207
Interface for buffered transformations.
Definition: cryptlib.h:1352
Password-Based Decryptor using TripleDES.
Definition: default.h:57
Pointer that overloads operator ->
Definition: smartptr.h:39
DefaultDecryptor(const char *passphrase, BufferedTransformation *attachment=NULL, bool throwException=true)
Constructs a DefaultDecryptor.
Definition: default.cpp:134
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:550
Filter wrapper for HashTransformation.
Definition: filters.h:521
size_t Put(byte inByte, bool blocking=true)
Input a byte for processing.
Definition: cryptlib.h:1376
#define CRYPTOPP_COMPILE_ASSERT(expr)
Compile time assertion.
Definition: misc.h:130
BufferedTransformation * AttachedTransformation()
Retrieve attached transformation.
Definition: filters.cpp:36
Indicates the message should be passed to an attached transformation.
Definition: filters.h:573
2-key TripleDES block cipher
Definition: des.h:75
SHA-1 message digest.
Definition: sha.h:25
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:491
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:905
const T & STDMAX(const T &a, const T &b)
Replacement function for std::max.
Definition: misc.h:487
Crypto++ library namespace.
virtual void Final(byte *digest)
Computes the hash of the current message.
Definition: cryptlib.h:960
void SetFilter(Filter *filter)
Sets the OutputProxy filter.
Definition: filters.cpp:496
DefaultDecryptorWithMAC(const char *passphrase, BufferedTransformation *attachment=NULL, bool throwException=true)
Constructs a DefaultDecryptor.
Definition: default.cpp:236
DefaultEncryptorWithMAC(const char *passphrase, BufferedTransformation *attachment=NULL)
Constructs a DefaultEncryptorWithMAC.
Definition: default.cpp:214