2 RainbowCrack - a general propose implementation of Philippe Oechslin's faster time-memory trade-off technique.
4 Copyright (C) Zhu Shuanglei <shuanglei@hotmail.com>
8 #pragma warning(disable : 4786)
11 #include "ChainWalkSet.h"
13 CChainWalkSet::CChainWalkSet()
15 m_sHashRoutineName = "";
16 m_sPlainCharsetName = "";
19 m_nRainbowTableIndex = 0;
20 m_nRainbowChainLen = 0;
22 sPrecalcPathName = "";
26 CChainWalkSet::~CChainWalkSet()
31 void CChainWalkSet::DiscardAll()
33 //printf("debug: discarding all walk...\n");
35 list<ChainWalk>::iterator it;
36 for (it = m_lChainWalk.begin(); it != m_lChainWalk.end(); it++)
41 string CChainWalkSet::CheckOrRotatePreCalcFile()
43 char sPreCalcFileName[255];
45 // 255 files limit to be sure
46 for (; preCalcPart < 255; preCalcPart++)
48 sprintf(sPreCalcFileName, "%s.%d", sPrecalcPathName.c_str(), preCalcPart);
49 string sReturnPreCalcPath(sPreCalcFileName);
51 unsigned int fileLen = 0;
53 FILE* file = fopen(sReturnPreCalcPath.c_str(), "ab");
56 fileLen = GetFileLen(file);
57 unsigned int nextFileLen = fileLen + (sizeof(uint64) * (m_nRainbowChainLen-1));
58 // Rotate to next file if we are going to pass 2GB filesize
59 if (nextFileLen < ((unsigned)2 * 1024 * 1024 * 1024))
61 // We might want to vPrecalcFiles.push_back(sReturnPreCalcPath) if we just created this file
62 // We don't as only newly generated chainwalksets will be stored to this new file, so we don't have to look there
63 if (debug) printf("Debug: Using for precalc: %s\n", sReturnPreCalcPath.c_str());
65 return sReturnPreCalcPath;
72 void CChainWalkSet::updateUsedPrecalcFiles()
74 // we might also use this function to search a wildcard path of precalc files
75 vPrecalcFiles.clear();
76 char sPreCalcFileName[255];
80 for (i = 0; i < 255; i++)
82 sprintf(sPreCalcFileName, "%s.%d", sPrecalcPathName.c_str(), i);
83 string sTryPreCalcPath(sPreCalcFileName);
84 FILE* file = fopen(sTryPreCalcPath.c_str(), "rb");
86 vPrecalcFiles.push_back(sTryPreCalcPath);
95 void CChainWalkSet::removePrecalcFiles()
97 if (debug) printf("Debug: Removing precalc files.\n");
98 updateUsedPrecalcFiles();
99 string sCurrentPrecalcPathName = "";
100 string sCurrentPrecalcIndexPathName = "";
103 for (i = 0; i < (int)vPrecalcFiles.size(); i++)
105 sCurrentPrecalcPathName = vPrecalcFiles[i];
106 sCurrentPrecalcIndexPathName = sCurrentPrecalcPathName + ".index";
108 if (debug) printf("Debug: Removing precalc file: %s\n", sCurrentPrecalcPathName.c_str());
110 if (remove(sCurrentPrecalcPathName.c_str()) != 0)
111 if (debug) printf("Debug: Failed removing precalc file: %s\n", sCurrentPrecalcPathName.c_str());
113 if (debug) printf("Debug: Removing precalc index file: %s\n", sCurrentPrecalcIndexPathName.c_str());
115 if (remove(sCurrentPrecalcIndexPathName.c_str()) != 0)
116 if (debug) printf("Debug: Failed removing precalc index file: %s\n", sCurrentPrecalcIndexPathName.c_str());
121 bool CChainWalkSet::FindInFile(uint64* pIndexE, unsigned char* pHash, int nHashLen)
123 int gotPrecalcOnLine = -1;
124 char precalculationLine[255];
125 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() );
126 string precalcString(precalculationLine);
128 string sCurrentPrecalcPathName = "";
129 string sCurrentPrecalcIndexPathName = "";
133 for (i = 0; i < (int)vPrecalcFiles.size() && gotPrecalcOnLine == -1; i++)
135 sCurrentPrecalcPathName = vPrecalcFiles[i];
136 sCurrentPrecalcIndexPathName = sCurrentPrecalcPathName + ".index";
140 vector<string> precalcLines;
141 if (ReadLinesFromFile(sCurrentPrecalcIndexPathName.c_str(), precalcLines))
144 for (j = 0; j < (int)precalcLines.size(); j++)
146 if (precalcString.compare(0, precalcString.size()-1, precalcLines[j]) == 0)
148 gotPrecalcOnLine = j;
153 vector<string> vPart;
154 if (SeperateString(precalcLines[j], "___:", vPart))
157 offset += ((atoi(vPart[3].c_str())-1) * sizeof(uint64));
161 printf("Corrupted precalculation file!\n");
162 gotPrecalcOnLine = -1;
169 if (gotPrecalcOnLine > -1)
171 if (debug) printf("Debug: Reading pre calculations from file, line %d offset %d\n", gotPrecalcOnLine, offset);
173 FILE* fp = fopen(sCurrentPrecalcPathName.c_str(), "rb");
176 fseek(fp, offset, SEEK_SET);
178 // We should do some verification here, for example by recalculating the middle chain, to catch corrupted files
179 if(fread(pIndexE, sizeof(uint64), m_nRainbowChainLen-1, fp) != m_nRainbowChainLen-1)
180 printf("File read error.");
184 printf("Cannot open precalculation file %s.\n", sCurrentPrecalcPathName.c_str());
186 //printf("\npIndexE[0]: %s\n", uint64tostr(pIndexE[0]).c_str());
187 //printf("\npIndexE[nRainbowChainLen-2]: %s\n", uint64tostr(pIndexE[m_nRainbowChainLen-2]).c_str());
196 void CChainWalkSet::StoreToFile(uint64* pIndexE, unsigned char* pHash, int nHashLen)
198 if (debug) printf("\nDebug: Storing precalc\n");
200 string sCurrentPrecalcPathName = CheckOrRotatePreCalcFile();
201 string sCurrentPrecalcIndexPathName = sCurrentPrecalcPathName + ".index";
203 FILE* fp = fopen(sCurrentPrecalcPathName.c_str(), "ab");
206 if(fwrite(pIndexE, sizeof(uint64), m_nRainbowChainLen-1, fp) != m_nRainbowChainLen-1)
207 printf("File write error.");
210 FILE* file = fopen(sCurrentPrecalcIndexPathName.c_str(), "a");
213 char precalculationLine[255];
214 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() );
215 fputs (precalculationLine, file);
222 printf("Cannot open precalculation file %s\n", sCurrentPrecalcPathName.c_str());
226 uint64* CChainWalkSet::RequestWalk(unsigned char* pHash, int nHashLen,
227 string sHashRoutineName,
228 string sPlainCharsetName, int nPlainLenMin, int nPlainLenMax,
229 int nRainbowTableIndex,
230 int nRainbowChainLen,
231 bool& fNewlyGenerated,
236 sPrecalcPathName = sPrecalc;
238 if ( m_sHashRoutineName != sHashRoutineName
239 || m_sPlainCharsetName != sPlainCharsetName
240 || m_nPlainLenMin != nPlainLenMin
241 || m_nPlainLenMax != nPlainLenMax
242 || m_nRainbowTableIndex != nRainbowTableIndex
243 || m_nRainbowChainLen != nRainbowChainLen)
247 m_sHashRoutineName = sHashRoutineName;
248 m_sPlainCharsetName = sPlainCharsetName;
249 m_nPlainLenMin = nPlainLenMin;
250 m_nPlainLenMax = nPlainLenMax;
251 m_nRainbowTableIndex = nRainbowTableIndex;
252 m_nRainbowChainLen = nRainbowChainLen;
255 memcpy(cw.Hash, pHash, nHashLen);
256 cw.pIndexE = new uint64[nRainbowChainLen - 1];
257 m_lChainWalk.push_back(cw);
259 // Only update this list when we search through another rainbow table
260 updateUsedPrecalcFiles();
262 if (!FindInFile(cw.pIndexE, pHash, nHashLen))
263 fNewlyGenerated = true;
265 fNewlyGenerated = false;
269 list<ChainWalk>::iterator it;
270 for (it = m_lChainWalk.begin(); it != m_lChainWalk.end(); it++)
272 if (memcmp(it->Hash, pHash, nHashLen) == 0)
274 fNewlyGenerated = false;
280 memcpy(cw.Hash, pHash, nHashLen);
281 cw.pIndexE = new uint64[nRainbowChainLen - 1];
282 m_lChainWalk.push_back(cw);
284 if (!FindInFile(cw.pIndexE, pHash, nHashLen))
285 fNewlyGenerated = true;
287 fNewlyGenerated = false;
291 void CChainWalkSet::DiscardWalk(uint64* pIndexE)
293 list<ChainWalk>::iterator it;
294 for (it = m_lChainWalk.begin(); it != m_lChainWalk.end(); it++)
296 if (it->pIndexE == pIndexE)
299 m_lChainWalk.erase(it);
304 printf("debug: pIndexE not found\n");