Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gteissier
GitHub Repository: gteissier/erl-matter
Path: blob/master/crack-prng.c
271 views
1
#include <stdio.h>
2
#include <stdint.h>
3
#include <stdlib.h>
4
#include <pthread.h>
5
#include <inttypes.h>
6
#include <assert.h>
7
8
#include "erldp.h"
9
10
static uint64_t next_random(uint64_t x);
11
static uint64_t iterated_random(uint64_t x, int times);
12
13
int fast_test_seed(uint64_t seed, const char *cookie, size_t size) {
14
uint64_t seed0, seed10, seed4;
15
16
seed0 = seed;
17
18
seed10 = iterated_random(seed0, 10);
19
if (cookie[19-10] != 'A' + ((26*seed10) / 0x1000000000))
20
return 1;
21
22
seed4 = iterated_random(seed0, 4);
23
if (cookie[19-4] != 'A' + ((26*seed4) / 0x1000000000))
24
return 1;
25
26
return 0;
27
}
28
29
int test_seed(uint64_t seed, const char *cookie, size_t size) {
30
uint64_t x;
31
int i;
32
33
x = seed;
34
35
for (i = size-1; i >= 0; i--) {
36
if (cookie[i] != 'A' + ((26*x) / 0x1000000000))
37
return size - i;
38
x = next_random(x);
39
}
40
41
return 0;
42
}
43
44
static uint64_t next_random(uint64_t x) {
45
unsigned __int128 z = x;
46
z = (z * 17059465ULL + 1) & 0xfffffffff;
47
return (uint64_t) z;
48
}
49
50
static uint64_t revert_random(uint64_t x) {
51
unsigned __int128 z = x;
52
z = ((z-1)*67451848633ULL) & 0xfffffffff;
53
return (uint64_t) z;
54
}
55
56
static const uint64_t a[20] = {17059465, 67081586001, 5731731033, 8693990305, 50580340521, 50510613233, 5704255737, 30394329921, 15524262857, 32648606865, 49299214233, 57662584545, 59097148521, 23224943153, 6786685497, 23686801025, 23383877897, 21534618577, 40671733977, 5654919713};
57
58
static const uint64_t b[20] = {1, 17059466, 67098645467, 4110899764, 12804890069, 63385230590, 45176367087, 50880622824, 12555476009, 28079738866, 60728345731, 41308083228, 30251191037, 20628862822, 43853805975, 50640491472, 5607815761, 28991693658, 50526312235, 22478569476};
59
60
static uint64_t iterated_random(uint64_t x, int times) {
61
assert(times >= 1 && times <= 20);
62
unsigned __int128 z = x;
63
z = (z * a[times-1] + b[times-1]) & 0xfffffffff;
64
return (uint64_t) z;
65
}
66
67
struct interval {
68
uint64_t start;
69
uint64_t end;
70
char c;
71
};
72
73
static const struct interval intervals[26] = {
74
{0ULL, 2643056797ULL, 'A'},
75
{2643056798ULL, 5286113595ULL, 'B'},
76
{5286113596ULL, 7929170392ULL, 'C'},
77
{7929170393ULL, 10572227190ULL, 'D'},
78
{10572227191ULL, 13215283987ULL, 'E'},
79
{13215283988ULL, 15858340785ULL, 'F'},
80
{15858340786ULL, 18501397582ULL, 'G'},
81
{18501397583ULL, 21144454380ULL, 'H'},
82
{21144454381ULL, 23787511177ULL, 'I'},
83
{23787511178ULL, 26430567975ULL, 'J'},
84
{26430567976ULL, 29073624772ULL, 'K'},
85
{29073624773ULL, 31716681570ULL, 'L'},
86
{31716681571ULL, 34359738367ULL, 'M'},
87
{34359738368ULL, 37002795165ULL, 'N'},
88
{37002795166ULL, 39645851963ULL, 'O'},
89
{39645851964ULL, 42288908760ULL, 'P'},
90
{42288908761ULL, 44931965558ULL, 'Q'},
91
{44931965559ULL, 47575022355ULL, 'R'},
92
{47575022356ULL, 50218079153ULL, 'S'},
93
{50218079154ULL, 52861135950ULL, 'T'},
94
{52861135951ULL, 55504192748ULL, 'U'},
95
{55504192749ULL, 58147249545ULL, 'V'},
96
{58147249546ULL, 60790306343ULL, 'W'},
97
{60790306344ULL, 63433363140ULL, 'X'},
98
{63433363141ULL, 66076419938ULL, 'Y'},
99
{66076419939ULL, 68719476735ULL, 'Z'}
100
};
101
102
volatile int quit = 0;
103
volatile uint64_t seed0 = 0;
104
105
struct worker {
106
pthread_t tid;
107
uint64_t start;
108
uint64_t end;
109
uint64_t incr;
110
const char *cookie;
111
};
112
113
static void *run(void *arg) {
114
struct worker *w = arg;
115
uint64_t seed;
116
117
for (seed = w->start; seed <= w->end && !quit; seed += w->incr) {
118
if (fast_test_seed(seed, w->cookie, 20) == 0 && test_seed(seed, w->cookie, 20) == 0) {
119
seed0 = seed;
120
//quit = 1;
121
}
122
}
123
124
return NULL;
125
}
126
127
128
int main(int argc, char **argv) {
129
const char *cookie;
130
int n_workers = 8;
131
struct worker *workers;
132
int c;
133
int i;
134
int ret;
135
uint64_t seed;
136
137
if (argc != 2) {
138
fprintf(stderr, "usage: %s <20 capital letters cookie>\n", argv[0]);
139
exit(1);
140
}
141
142
cookie = argv[1];
143
c = cookie[19] - 'A';
144
145
workers = calloc(sizeof(*workers), n_workers);
146
assert(workers);
147
148
for (i = 0; i < n_workers; i++) {
149
workers[i].start = intervals[c].start + i;
150
workers[i].end = intervals[c].end;
151
workers[i].incr = n_workers;
152
workers[i].cookie = cookie;
153
154
ret = pthread_create(&workers[i].tid, NULL, run, &workers[i]);
155
assert(ret == 0);
156
}
157
158
for (i = 0; i < n_workers; i++) {
159
pthread_join(workers[i].tid, NULL);
160
}
161
162
seed = revert_random(seed0);
163
printf("%" PRIu64 "\n", seed);
164
165
return 0;
166
}
167
168
169