aboutsummaryrefslogtreecommitdiffstats
path: root/checker/src/revhash/main.c
blob: 7a7b8026ca5e6384c2ece6ff28c049f2378b5363 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdint.h>

#define MAXITER   256 * 100
#define MHASHLEN  40
#define MAX(x,y)  ((x) > (y) ? (x) : (y))
#define MIN(x,y)  ((x) < (y) ? (x) : (y))

int
mhash(const char *str, size_t len)
{
	static char buf[MHASHLEN + 1];
	int i, k, v;
	char c, *bp;

	if (!str || !*str) str = ".";
	if (len <= 0) return EXIT_FAILURE;

	for (v = 0, i = 0; i < len; i++) v += str[i];

	srand(v);
	for (bp = buf, i = 0; i < MHASHLEN / 2; i++)
		bp += sprintf(bp, "%02x", str[i % len] ^ (rand() % 256));

	printf("%s\n", buf);

	return EXIT_SUCCESS;
}

int
hash()
{
	char str[256];
	size_t len;

	if (!fgets(str, sizeof(str), stdin))
		return EXIT_FAILURE;

	return mhash(str, strlen(str) - 1);
}

int
revhash(const char *hashstr)
{
	char c, hexbuf[3] = { 0 }, *end, buf[256];
	int i, k, v, maxlen, sum, hash[256], sublen, aftersum;

	if (strlen(hashstr) % 2 != 0)
		goto invalid;
	maxlen = strlen(hashstr) / 2;

	/* convert hex to int array */
	for (i = 0; i < maxlen; i++) {
		memcpy(hexbuf, hashstr + 2 * i, 2);
		hash[i] = strtol(hexbuf, &end, 16);
		if (end && *end) goto invalid;
	}

	/* bruteforce srand seed */
	for (i = 0; i < MAXITER; i++) {
		srand(i);

		/* reverse chars for given sum */
		for (sum = i, k = 0; k < maxlen && sum > 0; k++) {
			buf[k] = (char) hash[k] ^ (rand() % 256);
			if (buf[k] < 0) break;
			sum -= buf[k];
		}

		/* repeat if too short */
		if (k && sum == 0) {
			sublen = k;
			for (k = sublen; k < maxlen; k++) {
				buf[k] = (char) hash[k] ^ (rand() % 256);
				if (buf[k] < 0 || buf[k] != buf[k % sublen]) break;
			}
		} else {
			sublen = maxlen;
		}

		if (k < maxlen) continue;

		/* output first part we know */
		printf("%.*s", sublen, buf);

		/* add rest of chars */
		while (sum > 0) {
			c = MIN(127, sum);
			printf("%c", c);
			sum -= c;
			buf[k++] = c;
		}

		printf("\n");

		if (getenv("OUTPUT_HASH"))
			mhash(buf, k);

		return EXIT_SUCCESS;
	}

	return EXIT_FAILURE;

invalid:
	fprintf(stderr, "Invalid hash string!\n");
	return EXIT_FAILURE;
}

int
main(int argc, const char **argv)
{
	if (argc < 2) {
		fprintf(stderr, "USAGE: revhash <hash>\n");
		return EXIT_FAILURE;
	}

	if (!strcmp(argv[1], "hash"))
		return hash();
	else
		return revhash(argv[1]);
}