-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcsv2gmp.c
259 lines (224 loc) · 6.69 KB
/
csv2gmp.c
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
// copri, Attacking RSA by factoring coprimes
//
// License: GNU Lesser General Public License (LGPL), version 3 or later
// See the lgpl.txt file in the root directory or <https://www.gnu.org/licenses/lgpl>.
// Read public_key.csv from [scans.io](https://scans.io/study/umich-https) and convert it to
// copri compatible raw gmp format.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <gmp.h>
#define READ_BUF_SIZE 8192
#define DEFAULT_MIN_LENGTH 512
#define DEFAULT_MAX_LENGTH 8192
typedef void (*readline_cb_t)(char* line, unsigned int len);
void readline(FILE *fp, readline_cb_t readline_cb, unsigned int read_buffer_size);
void readline_cb(char* line, unsigned int len);
FILE *out;
long int min_length = DEFAULT_MIN_LENGTH;
long int max_length = DEFAULT_MAX_LENGTH;
size_t key_count = 0;
// Define the variables set by the argument parser
int c, vflg = 0, errflg = 0;
// # main
// Read the command line arguments, open the output file and the csv file then
// start appending rsa key `n` values read from csv in raw gmp format to the
// output file.
int main (int argc, char *argv[]) {
FILE *csv;
char* csv_filename = "-";
char* out_filename = "-";
// Read the command line arguments.
while ((c = getopt(argc, argv, ":vcpg:l:o:")) != -1) {
switch(c) {
case 'v':
vflg++;
break;
case 'g':
min_length = strtol(optarg, NULL, 0);
if (min_length < 1) errflg++;
break;
case 'l':
max_length = strtol(optarg, NULL, 0);
if (max_length < 1) errflg++;
break;
case 'o':
out_filename = optarg;
break;
case ':':
fprintf(stderr, "Option -%c requires an operand\n", optopt);
errflg++;
break;
case '?':
fprintf(stderr, "Unrecognized option: '-%c'\n", optopt);
errflg++;
}
}
if (optind < argc) {
csv_filename = argv[optind];
if (optind + 1 < argc) errflg++;
}
// Print the usage and exit if an error occurred during argument parsing.
if (errflg) {
fprintf(stderr, "usage: [-vc] [-g min_keylength] [-l max_keylength] [-o gmp_file] [csv_file]\n"\
"\n\t-v be more verbose"\
"\n"\
"\n\t-g MIN_KEYLENGTH the minimal key length (>=)"\
"\n\t-l MAX_KEYLENGTH the maximum key length (<=)"\
"\n\t-o GMP_FILE the gmp file to write"\
"\n\n");
exit(2);
}
// Set `out` to `stdout` if the filename is `-`.
if (strcmp(out_filename, "-") == 0) {
out = stdout;
// Print the used parameters if the verbose flag is set.
if (vflg > 0) {
fprintf(stderr, "Printing RSA n values in raw gmp format to stdout.\n");
}
} else {
// Open the output file.
out = fopen(out_filename, "a+");
if (out == NULL) {
printf("Cannot save to file %s.\n", out_filename);
exit(3);
}
// Print the used parameters if the verbose flag is set.
if (vflg > 0) {
fprintf(stderr, "Adding RSA n values to file %s.\n", out_filename);
}
}
// Set `csv` to `stdin` if the filename is `-`.
if (strcmp(csv_filename, "-") == 0) {
csv = stdin;
// Print the used parameters if the verbose flag is set.
if (vflg > 0) {
fprintf(stderr, "Reading CSV from stdin.\n");
}
} else {
// Open the csv file.
csv = fopen(csv_filename, "rt");
if (csv == NULL) {
printf("Cannot read %s.\n", csv_filename);
exit(4);
}
// Print the used parameters if the verbose flag is set.
if (vflg > 0) {
fprintf(stderr, "Reading CSV from %s.\n", csv_filename);
}
}
// This calls `readline_cb` on every line of `csv`.
readline(csv, readline_cb, READ_BUF_SIZE);
// Colse the files.
fclose(csv);
fclose(out);
// Print the summary.
if (vflg > 0) {
fprintf(stderr, "%zu raw gmp keys have been writen to %s.\n", key_count, out_filename);
}
return 0;
}
void readline_cb(char* line, unsigned int len) {
size_t write_len = 0;
unsigned int c = 0;
unsigned int c_start = 0;
unsigned int c_end = 0;
int is_rsa = 0;
long int keylength = 0;
mpz_t key;
// Parse the line.
for (c_end = 0; c_end<=len; c_end++) {
if (line[c_end] == ',' || c_end == len) {
line[c_end] = '\0';
// Check if the second column contains "rsaEncryption".
if (c == 1) {
if (strncmp(line+c_start, "rsaEncryption", c_end-c_start) == 0) {
is_rsa = 1;
}
// Store the fourth column as `mpz_t`.
} else if(is_rsa && c == 4) {
mpz_init(key);
mpz_set_str(key, line+c_start+2, 16);
// Store the tenth column as the key length.
} else if(is_rsa && c == 9) {
keylength = strtol(line+c_start, NULL, 0);
}
c++;
c_start = c_end+1;
}
}
// If the is an RSA key and the key length condition is meet write the
// key in raw gmp format to `out`.
if (is_rsa && keylength >= min_length && keylength <= max_length) {
write_len = mpz_out_raw(out, key);
if (write_len == 0) {
fprintf(stderr, "Cannot write to file.\n");
} else {
key_count++;
}
}
// Free the memory.
if (is_rsa) {
mpz_clear(key);
}
}
// # readline
//
// read the file and call `readline_cb` on every line.
void readline(FILE *fp, readline_cb_t readline_cb, unsigned int read_buffer_size) {
char *line_buf;
unsigned int line_buf_size = 1024;
unsigned int line_buf_index = 0;
char read_buf[read_buffer_size];
unsigned int line_start = 0;
unsigned int line_end = 0;
unsigned int line_chunck_size = 0;
unsigned int i = 0;
size_t bytes_read = 0;
unsigned int x = 0;
// Alloc the line buffer by guessed size.
line_buf = malloc(line_buf_size);
for (x = 0; x<line_buf_size; x++)
line_buf[x] = '?';
// Start looping until the end of the file is reached.
while(!feof(fp))
{
// Read the next `read_buffer_size` chunck of the file.
bytes_read = fread(&read_buf, 1, read_buffer_size, fp);
// Loop until the end of the chunck.
while (line_end < bytes_read)
{
// Find the index of the next `\n` char.
while (line_end < bytes_read && read_buf[line_end] != '\n')
line_end++;
// Store the size of line chunck.
line_chunck_size = line_end - line_start;
// Increase the size of the line buffer if needed.
while (line_buf_index+line_chunck_size+1 > line_buf_size)
{
line_buf_size *= 2;
line_buf = realloc(line_buf, line_buf_size);
}
// Copy the read buffer to the line buffer.
for (i=0; i<line_chunck_size; i++)
line_buf[line_buf_index+i] = read_buf[line_start+i];
// Set the new line start index and terminate the string by `\0`.
line_buf_index += i;
line_buf[line_buf_index] = '\0';
// Call the readline function if the line buffer ends with `\n`
if (read_buf[line_end] == '\n') {
readline_cb(line_buf, line_buf_index);
line_buf_index = 0;
}
// Move the chunck to the next index.
line_end++;
line_start = line_end;
}
// Reset the line indices.
line_start = 0;
line_end = 0;
}
// Free the line buffer.
free(line_buf);
}