Ejemplo n.º 1
0
		void initialize(std::vector<stringT> const & words) {
			this->words = words;
			isInitialized = true;
			// construct trie
			trie.clear();
			trie.push_back(trie_node());
			for(size_t i = 0; i < words.size(); ++i) {
				stringT const & word = words[i];
				for(C & c: word) {
					trie_node & current = trie[nodeIndex];
					std::unordered_map<C,int> & edges = current.edges;
					auto nextIt = edges.find(c);
					if(nextIt == edges.end()) {
						trie_node t;
						t.fail_index = 0;
						t.parent_index = nodeIndex;
						nodeIndex = trie.size();
						trie.push_back(t);
						edges[c] = nodeIndex;
					}
					nodeIndex = edges[c];
				}
				trie[nodeIndex].endOf.insert(i);
			}
			// construct fallback
			std::queue<int> Q;
			Q.push(0);
			while(!Q.empty()) {
				int cur = Q.front();
				Q.pop();
				for(std::pair<C, int> kvp : trie[cur].edges) {
					// unpack pair
					C a = kvp.first;
					int u = kvp.second;
					trie_node & U = trie[u];
					// queue destination
					Q.push(u);
					// find next fail index
					int v = U.fail_index;
					if(v == 0) {
						std::unordered_map<C,int> & edges = trie[0].edges;
						if(edges.find(a) == edges.end())
							U.fail_index = 0;
						else
							U.fail_index = edges[a];
					}
					else {
						while(trie[v].edges.find(a) == trie[v].edges.end())
							v = trie[v].fail_index;
						U.fail_index = trie[v].edges[a];
					}
					std::set<int> & failEndings = trie[U.fail_index].endOf;
					U.endOf.insert(begin(failEndings), end(failEndings));
				}
			}
		}
Ejemplo n.º 2
0
int main(int argc, char** argv)
{
	void* input = fopen("cipher1.txt", "r");
	void* words = fopen("words.txt", "r");
	int c, n;
	char* cipher = malloc(1024 * 1024 * 100);
	char* p;
	char buf[1024] = "";
	char best_passwd[10] = "failed";
	int pass[4];
	int i = 0;
	int cipher_length;
	int j;
	trie* t = trie_node();
	trie* node;
	int wc;
	int record = 0;
	int sum;

	if(!input) error("could not open cipher file");
	if(!words) error("could not open words file");
	if(!t)	error("could not create trie");

	printf("reading in cipher\n");
	while(!feof(input)) {
		p = buf;
		while((c = fgetc(input)) != ',' && c >= 0) {
			*(p++) = c;
		}
		*p = 0;
		sscanf(buf, "%d", &n);
		cipher[i++] = n;
		printf("got %d -> %d\n", n, i);
	}
	cipher_length = i;

	printf("reading in words\n");
	while(1) {
		if(fgets(buf, 1024, words) == 0) break;
		p = buf;
		node = t;
		while(*p && *p != '\n') {
			if(!node->map[*p])
				if(!(node->map[*p] = trie_node()))
					error("trie node allocation");
			node = node->map[*p];
			++p;
		}
		node->entry = 1;		
	}

	pass[0] = pass[1] = pass[2] = 'a';
	pass[3] = 0;
	while(!pass[3]) {
		for(i = 0; i <= 3; i++)
			if(pass[i] > 'z')
			{
				pass[i] = 'a';
				pass[i+1]++;
			}

		node = t;

		wc = 0;
		for(i = 0; i < cipher_length; i++) {
			if(node->map[cipher[i] ^ (pass[i % 3])] != 0
			 && isalnum(cipher[i] ^ (pass[i % 3]))) {
				node = node->map[cipher[i] ^ (pass[i % 3])];
				*p++ = (cipher[i] ^ (pass[i % 3]));
				*p = 0;			
			}
			else
				goto clear_up;

			if(node->entry && strlen(buf) > 3) {
				++wc;
				printf("password %c%c%c; found word: %s\n", *pass, pass[1], pass[2], buf);
clear_up:
				*buf = 0;
				p = buf;
				node = t;
			}
		}

		if(wc > record) {
			record = wc;
			sprintf(best_passwd, "%c%c%c", *pass, pass[1], pass[2]);
		}

		++*pass;
	}

	printf("best password found was '%s', which yielded %d wordfinds.\n", best_passwd, record);
	printf("decrypted message:\n");
	
	for(i = 0; i < cipher_length; i++)
		putchar(cipher[i] ^ best_passwd[i % 3]);
	printf("\n");

	sum = 0;
	for(i = 0; i < cipher_length; i++)
		sum += cipher[i] ^ best_passwd[i % 3];
	
	printf("ascii sum: %d\n", sum);
	return 0;	
}