]> git.sesse.net Git - freerainbowtables/blob - Common/rt api/ChainWalkSet.cpp
(C)
[freerainbowtables] / Common / rt api / ChainWalkSet.cpp
1 /*
2  * freerainbowtables is a project for generating, distributing, and using
3  * perfect rainbow tables
4  *
5  * Copyright (C) Zhu Shuanglei <shuanglei@hotmail.com>
6  * Copyright Martin Westergaard Jørgensen <martinwj2005@gmail.com>
7  * Copyright 2009, 2010 Daniël Niggebrugge <niggebrugge@fox-it.com>
8  * Copyright 2009, 2010, 2011 James Nobis <frt@quelrod.net>
9  *
10  * This file is part of freerainbowtables.
11  *
12  * freerainbowtables is free software: you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation, either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * freerainbowtables is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with freerainbowtables.  If not, see <http://www.gnu.org/licenses/>.
24  */
25
26 #if defined(_WIN32) && !defined(__GNUC__)
27         #pragma warning(disable : 4786)
28 #endif
29
30 #include "ChainWalkSet.h"
31
32 CChainWalkSet::CChainWalkSet()
33 {
34         m_sHashRoutineName   = "";
35         m_sPlainCharsetName  = "";
36         m_nPlainLenMin       = 0;
37         m_nPlainLenMax       = 0;
38         m_nRainbowTableIndex = 0;
39         m_nRainbowChainLen   = 0;
40         debug = false;
41         sPrecalcPathName     = "";
42         preCalcPart          = 0;
43 }
44
45 CChainWalkSet::~CChainWalkSet()
46 {
47         DiscardAll();
48 }
49
50 void CChainWalkSet::DiscardAll()
51 {
52         //printf("debug: discarding all walk...\n");
53
54         list<ChainWalk>::iterator it;
55         for (it = m_lChainWalk.begin(); it != m_lChainWalk.end(); it++)
56                 delete [] it->pIndexE;
57         m_lChainWalk.clear();
58 }
59
60 string CChainWalkSet::CheckOrRotatePreCalcFile()
61 {
62         char sPreCalcFileName[255];
63
64         // 255 files limit to be sure
65         for (; preCalcPart < 255; preCalcPart++)
66         {
67                 sprintf(sPreCalcFileName, "%s.%d", sPrecalcPathName.c_str(), preCalcPart);
68                 string sReturnPreCalcPath(sPreCalcFileName);
69
70                 long fileLen = 0;
71
72                 FILE* file = fopen(sReturnPreCalcPath.c_str(), "ab");
73                 if(file!=NULL)
74                 {
75                         fileLen = GetFileLen(file);
76                         long unsigned int nextFileLen = fileLen + (sizeof(uint64) * (m_nRainbowChainLen-1));
77                         // Rotate to next file if we are going to pass 2GB filesize
78                         if (nextFileLen < ((unsigned)2 * 1024 * 1024 * 1024))
79                         {
80                                 // We might want to vPrecalcFiles.push_back(sReturnPreCalcPath) if we just created this file
81                                 // We don't as only newly generated chainwalksets will be stored to this new file, so we don't have to look there
82                                 if (debug) printf("Debug: Using for precalc: %s\n", sReturnPreCalcPath.c_str());
83                                 fclose(file);
84                                 return sReturnPreCalcPath;
85                         }
86                         fclose(file);
87                 }
88         }
89
90         return string("");
91 }
92
93 void CChainWalkSet::updateUsedPrecalcFiles()
94 {
95         // we might also use this function to search a wildcard path of precalc files
96         vPrecalcFiles.clear();
97         char sPreCalcFileName[255];
98
99         int i;
100         // 255 files max
101         for (i = 0; i < 255; i++)
102         {
103                 sprintf(sPreCalcFileName, "%s.%d", sPrecalcPathName.c_str(), i);
104                 string sTryPreCalcPath(sPreCalcFileName);
105                 FILE* file = fopen(sTryPreCalcPath.c_str(), "rb");
106                 if(file!=NULL) {
107                         vPrecalcFiles.push_back(sTryPreCalcPath);
108                         fclose(file);
109                 }
110                 else {
111                         break;
112                 }
113         }
114 }
115
116 void CChainWalkSet::removePrecalcFiles()
117 {
118         if (debug) printf("Debug: Removing precalc files.\n");
119         updateUsedPrecalcFiles();
120         string sCurrentPrecalcPathName = "";
121         string sCurrentPrecalcIndexPathName = "";
122         
123         int i;
124         for (i = 0; i < (int)vPrecalcFiles.size(); i++)
125         {
126                 sCurrentPrecalcPathName = vPrecalcFiles[i];
127                 sCurrentPrecalcIndexPathName = sCurrentPrecalcPathName + ".index";
128
129                 if (debug) printf("Debug: Removing precalc file: %s\n", sCurrentPrecalcPathName.c_str());
130
131                 if (remove(sCurrentPrecalcPathName.c_str()) != 0)
132                         if (debug) printf("Debug: Failed removing precalc file: %s\n", sCurrentPrecalcPathName.c_str());
133
134                 if (debug) printf("Debug: Removing precalc index file: %s\n", sCurrentPrecalcIndexPathName.c_str());
135
136                 if (remove(sCurrentPrecalcIndexPathName.c_str()) != 0)
137                         if (debug) printf("Debug: Failed removing precalc index file: %s\n", sCurrentPrecalcIndexPathName.c_str());
138
139         }
140 }
141
142 bool CChainWalkSet::FindInFile(uint64* pIndexE, unsigned char* pHash, int nHashLen)
143 {
144         int gotPrecalcOnLine = -1;
145         char precalculationLine[255];
146         sprintf(precalculationLine, "%s_%s#%d-%d_%d_%d:%s\n", m_sHashRoutineName.c_str(), m_sPlainCharsetName.c_str(), m_nPlainLenMin, m_nPlainLenMax, m_nRainbowTableIndex, m_nRainbowChainLen, HexToStr(pHash, nHashLen).c_str() );
147         string precalcString(precalculationLine);
148
149         string sCurrentPrecalcPathName = "";
150         string sCurrentPrecalcIndexPathName = "";
151         long unsigned int offset;
152
153         int i;
154         for (i = 0; i < (int)vPrecalcFiles.size() && gotPrecalcOnLine == -1; i++)
155         {
156                 sCurrentPrecalcPathName = vPrecalcFiles[i];
157                 sCurrentPrecalcIndexPathName = sCurrentPrecalcPathName + ".index";
158
159                 offset = 0;
160
161                 vector<string> precalcLines;
162                 if (ReadLinesFromFile(sCurrentPrecalcIndexPathName.c_str(), precalcLines))
163                 {
164                         int j;
165                         for (j = 0; j < (int)precalcLines.size(); j++)
166                         {
167                                 if (precalcString.compare(0, precalcString.size()-1, precalcLines[j]) == 0)
168                                 {
169                                         gotPrecalcOnLine = j;
170                                         break;
171                                 }
172
173                                 // Parse
174                                 vector<string> vPart;
175                                 if (SeperateString(precalcLines[j], "___:", vPart))
176                                 {
177                                         // add to offset
178                                         offset += ((atoi(vPart[3].c_str())-1) * sizeof(uint64));
179                                 }
180                                 else {
181                                         // corrupt file
182                                         printf("Corrupted precalculation file!\n");
183                                         gotPrecalcOnLine = -1;
184                                         break;
185                                 }
186                         }
187                 }
188         }
189
190         if (gotPrecalcOnLine > -1)
191         {
192                 if (debug) printf("Debug: Reading pre calculations from file, line %d offset %lu\n", gotPrecalcOnLine, offset);
193                 
194                 FILE* fp = fopen(sCurrentPrecalcPathName.c_str(), "rb");
195
196                 if (fp!=NULL) {
197                         fseek(fp, offset, SEEK_SET);
198
199                         // We should do some verification here, for example by recalculating the middle chain, to catch corrupted files
200                         if(fread(pIndexE, sizeof(uint64), (unsigned long)m_nRainbowChainLen-1, fp) != (unsigned long)m_nRainbowChainLen-1)
201                                 printf("File read error.");
202                         fclose(fp);
203                 }
204                 else
205                         printf("Cannot open precalculation file %s.\n", sCurrentPrecalcPathName.c_str());
206
207                 //printf("\npIndexE[0]: %s\n", uint64tostr(pIndexE[0]).c_str());
208                 //printf("\npIndexE[nRainbowChainLen-2]: %s\n", uint64tostr(pIndexE[m_nRainbowChainLen-2]).c_str());
209
210                 return true;
211         }
212
213         return false;
214 }
215
216 void CChainWalkSet::StoreToFile(uint64* pIndexE, unsigned char* pHash, int nHashLen)
217 {
218         if (debug) printf("\nDebug: Storing precalc\n");
219         
220         string sCurrentPrecalcPathName = CheckOrRotatePreCalcFile();
221         string sCurrentPrecalcIndexPathName = sCurrentPrecalcPathName + ".index";
222
223         FILE* fp = fopen(sCurrentPrecalcPathName.c_str(), "ab");
224         if(fp!=NULL)
225         {
226                 if(fwrite(pIndexE, sizeof(uint64), (unsigned long)m_nRainbowChainLen-1, fp) != (unsigned long)m_nRainbowChainLen-1)
227                         printf("File write error.");
228                 else
229                 {
230                         FILE* file = fopen(sCurrentPrecalcIndexPathName.c_str(), "a");
231                         if (file!=NULL)
232                         {
233                                 char precalculationLine[255];
234                                 sprintf(precalculationLine, "%s_%s#%d-%d_%d_%d:%s\n", m_sHashRoutineName.c_str(), m_sPlainCharsetName.c_str(), m_nPlainLenMin, m_nPlainLenMax, m_nRainbowTableIndex, m_nRainbowChainLen, HexToStr(pHash, nHashLen).c_str() );
235                                 fputs (precalculationLine, file);
236                                 fclose (file);
237                         }
238                 }
239                 fclose(fp);
240                 }
241         else
242                 printf("Cannot open precalculation file %s\n", sCurrentPrecalcPathName.c_str());
243 }
244
245 uint64* CChainWalkSet::RequestWalk(unsigned char* pHash, int nHashLen,
246                                                                    string sHashRoutineName,
247                                                                    string sPlainCharsetName, int nPlainLenMin, int nPlainLenMax, 
248                                                                    int nRainbowTableIndex, 
249                                                                    int nRainbowChainLen,
250                                                                    bool& fNewlyGenerated,
251                                                                    bool setDebug,
252                                                                    string sPrecalc)
253 {
254         debug = setDebug;
255         sPrecalcPathName = sPrecalc;
256
257         if (   m_sHashRoutineName   != sHashRoutineName
258                 || m_sPlainCharsetName  != sPlainCharsetName
259                 || m_nPlainLenMin       != nPlainLenMin
260                 || m_nPlainLenMax       != nPlainLenMax
261                 || m_nRainbowTableIndex != nRainbowTableIndex
262                 || m_nRainbowChainLen   != nRainbowChainLen)
263         {
264                 DiscardAll();
265
266                 m_sHashRoutineName   = sHashRoutineName;
267                 m_sPlainCharsetName  = sPlainCharsetName;
268                 m_nPlainLenMin       = nPlainLenMin;
269                 m_nPlainLenMax       = nPlainLenMax;
270                 m_nRainbowTableIndex = nRainbowTableIndex;
271                 m_nRainbowChainLen   = nRainbowChainLen;
272
273                 ChainWalk cw;
274                 memcpy(cw.Hash, pHash, nHashLen);
275                 cw.pIndexE = new uint64[nRainbowChainLen - 1];
276                 m_lChainWalk.push_back(cw);
277
278                 // Only update this list when we search through another rainbow table
279                 updateUsedPrecalcFiles();
280
281                 if (!FindInFile(cw.pIndexE, pHash, nHashLen))
282                         fNewlyGenerated = true;
283                 else
284                         fNewlyGenerated = false;
285                 return cw.pIndexE;
286         }
287
288         list<ChainWalk>::iterator it;
289         for (it = m_lChainWalk.begin(); it != m_lChainWalk.end(); it++)
290         {
291                 if (memcmp(it->Hash, pHash, nHashLen) == 0)
292                 {
293                         fNewlyGenerated = false;
294                         return it->pIndexE;
295                 }
296         }
297
298         ChainWalk cw;
299         memcpy(cw.Hash, pHash, nHashLen);
300         cw.pIndexE = new uint64[nRainbowChainLen - 1];
301         m_lChainWalk.push_back(cw);
302
303         if (!FindInFile(cw.pIndexE, pHash, nHashLen))
304                         fNewlyGenerated = true;
305                 else
306                         fNewlyGenerated = false;
307         return cw.pIndexE;
308 }
309
310 void CChainWalkSet::DiscardWalk(uint64* pIndexE)
311 {
312         list<ChainWalk>::iterator it;
313         for (it = m_lChainWalk.begin(); it != m_lChainWalk.end(); it++)
314         {
315                 if (it->pIndexE == pIndexE)
316                 {
317                         delete it->pIndexE;
318                         m_lChainWalk.erase(it);
319                         return;
320                 }
321         }
322
323         printf("debug: pIndexE not found\n");
324 }