1// file_encrypt_v2.c
2// ๊ฐ์ ๋ ํ์ผ ์ํธํ ๋๊ตฌ (ํค๋ + ํค ๊ฒ์ฆ)
3// ํ์ต ๋ชฉ์ : ๊ตฌ์กฐ์ฒด, ํ์ผ ํค๋, ํด์ ํจ์, ํฅ์๋ ์๋ฌ ์ฒ๋ฆฌ
4
5#include <stdio.h>
6#include <stdlib.h>
7#include <string.h>
8#include <stdint.h>
9
10// ์์ ์ ์
11#define MAGIC "XENC" // ํ์ผ ์๋ณ์ฉ ๋งค์ง ๋๋ฒ
12#define VERSION 1 // ํ์ผ ํฌ๋งท ๋ฒ์
13#define BUFFER_SIZE 4096 // 4KB ๋ฒํผ
14#define HEADER_SIZE 17 // ํค๋ ํฌ๊ธฐ (๋ฐ์ดํธ)
15
16/**
17 * ์ํธํ ํ์ผ ํค๋ ๊ตฌ์กฐ์ฒด
18 *
19 * ๊ตฌ์กฐ:
20 * - magic[4]: "XENC" ๋งค์ง ๋๋ฒ (ํ์ผ ์๋ณ)
21 * - version: ํ์ผ ํฌ๋งท ๋ฒ์ (1๋ฐ์ดํธ)
22 * - key_hash: ํค์ ํด์๊ฐ (4๋ฐ์ดํธ, ํค ๊ฒ์ฆ์ฉ)
23 * - original_size: ์๋ณธ ํ์ผ ํฌ๊ธฐ (8๋ฐ์ดํธ)
24 */
25typedef struct {
26 char magic[4]; // ๋งค์ง ๋๋ฒ: "XENC"
27 uint8_t version; // ๋ฒ์ : 1
28 uint32_t key_hash; // ํค ํด์ (djb2)
29 uint64_t original_size; // ์๋ณธ ํ์ผ ํฌ๊ธฐ
30} FileHeader;
31
32// ํจ์ ์ ์ธ
33void print_usage(const char *name);
34uint32_t hash_key(const char *key);
35void xor_buffer(unsigned char *buf, size_t len, const char *key, size_t key_len, size_t *pos);
36int encrypt_file(const char *input, const char *output, const char *key);
37int decrypt_file(const char *input, const char *output, const char *key);
38int show_info(const char *filename);
39
40/**
41 * ๊ฐ๋จํ ํด์ ํจ์ (djb2 ์๊ณ ๋ฆฌ์ฆ)
42 *
43 * @param key ํด์ํ ๋ฌธ์์ด
44 * @return 32๋นํธ ํด์๊ฐ
45 *
46 * djb2๋ Daniel J. Bernstein์ด ๋ง๋ ๊ฐ๋จํ์ง๋ง ํจ๊ณผ์ ์ธ ํด์ ํจ์
47 * ์ด๊ธฐ๊ฐ: 5381
48 * ๊ณต์: hash = hash * 33 + c
49 */
50uint32_t hash_key(const char *key) {
51 uint32_t hash = 5381;
52 int c;
53
54 while ((c = *key++)) {
55 // hash * 33 + c = (hash << 5) + hash + c
56 hash = ((hash << 5) + hash) + c;
57 }
58
59 return hash;
60}
61
62/**
63 * ์ฌ์ฉ๋ฒ ์ถ๋ ฅ
64 */
65void print_usage(const char *name) {
66 printf("๊ฐ์ ๋ ํ์ผ ์ํธํ ๋๊ตฌ v2\n\n");
67 printf("์ฌ์ฉ๋ฒ:\n");
68 printf(" %s encrypt <์
๋ ฅํ์ผ> <์ถ๋ ฅํ์ผ> <๋น๋ฐ๋ฒํธ>\n", name);
69 printf(" %s decrypt <์
๋ ฅํ์ผ> <์ถ๋ ฅํ์ผ> <๋น๋ฐ๋ฒํธ>\n", name);
70 printf(" %s info <์ํธํํ์ผ>\n", name);
71 printf("\n์์ :\n");
72 printf(" %s encrypt secret.txt secret.enc mypassword\n", name);
73 printf(" %s decrypt secret.enc decrypted.txt mypassword\n", name);
74 printf(" %s info secret.enc\n", name);
75}
76
77/**
78 * ๋ฒํผ๋ฅผ XOR ์ํธํ/๋ณตํธํ (ํค ์์น ์ถ์ )
79 *
80 * @param buf ์ฒ๋ฆฌํ ๋ฒํผ
81 * @param len ๋ฒํผ ๊ธธ์ด
82 * @param key ์ํธํ ํค
83 * @param key_len ํค ๊ธธ์ด
84 * @param pos ํค์ ํ์ฌ ์์น (ํฌ์ธํฐ, ์ํ ์ ์ง)
85 *
86 * pos ๋งค๊ฐ๋ณ์๋ก ์ฌ๋ฌ ๋ฒํผ์ ๊ฑธ์ณ ํค ์์น๋ฅผ ์ฐ์์ ์ผ๋ก ์ถ์
87 * ์ด๋ ๊ฒ ํ๋ฉด ํ์ผ์ ์ฌ๋ฌ ๋ธ๋ก์ผ๋ก ๋๋ ์ฝ์ด๋ ํค ํจํด์ด ์ผ๊ด๋จ
88 */
89void xor_buffer(unsigned char *buf, size_t len, const char *key, size_t key_len, size_t *pos) {
90 for (size_t i = 0; i < len; i++) {
91 buf[i] ^= key[*pos % key_len];
92 (*pos)++; // ํค ์์น ์ฆ๊ฐ
93 }
94}
95
96/**
97 * ํ์ผ ์ํธํ (ํค๋ ํฌํจ)
98 *
99 * @param input ์
๋ ฅ ํ์ผ ๊ฒฝ๋ก
100 * @param output ์ถ๋ ฅ ํ์ผ ๊ฒฝ๋ก
101 * @param key ์ํธํ ํค
102 * @return ์ฑ๊ณต ์ 0, ์คํจ ์ 1
103 */
104int encrypt_file(const char *input, const char *output, const char *key) {
105 // ์
๋ ฅ ํ์ผ ์ด๊ธฐ
106 FILE *fin = fopen(input, "rb");
107 if (!fin) {
108 perror("์
๋ ฅ ํ์ผ ์ด๊ธฐ ์คํจ");
109 return 1;
110 }
111
112 // ์๋ณธ ํ์ผ ํฌ๊ธฐ ํ์ธ
113 fseek(fin, 0, SEEK_END);
114 uint64_t file_size = ftell(fin);
115 fseek(fin, 0, SEEK_SET);
116
117 // ์ถ๋ ฅ ํ์ผ ์ด๊ธฐ
118 FILE *fout = fopen(output, "wb");
119 if (!fout) {
120 perror("์ถ๋ ฅ ํ์ผ ์ด๊ธฐ ์คํจ");
121 fclose(fin);
122 return 1;
123 }
124
125 // ํค๋ ๊ตฌ์กฐ์ฒด ์ด๊ธฐํ
126 FileHeader header;
127 memcpy(header.magic, MAGIC, 4); // "XENC" ๋ณต์ฌ
128 header.version = VERSION; // ๋ฒ์ 1
129 header.key_hash = hash_key(key); // ํค์ ํด์๊ฐ ์ ์ฅ
130 header.original_size = file_size; // ์๋ณธ ํฌ๊ธฐ ์ ์ฅ
131
132 // ํค๋๋ฅผ ํ์ผ์ ๊ธฐ๋ก
133 fwrite(&header, sizeof(FileHeader), 1, fout);
134
135 // ๋ฐ์ดํฐ ์ํธํ
136 unsigned char buffer[BUFFER_SIZE];
137 size_t bytes_read;
138 size_t key_len = strlen(key);
139 size_t key_pos = 0; // ํค ์์น ์ถ์
140
141 printf("์ํธํ ์ค...\n");
142 while ((bytes_read = fread(buffer, 1, BUFFER_SIZE, fin)) > 0) {
143 xor_buffer(buffer, bytes_read, key, key_len, &key_pos);
144 fwrite(buffer, 1, bytes_read, fout);
145
146 // ๊ฐ๋จํ ์งํ๋ฅ ํ์
147 printf(".");
148 fflush(stdout);
149 }
150 printf("\n");
151
152 fclose(fin);
153 fclose(fout);
154
155 printf("์ํธํ ์๋ฃ: %s -> %s\n", input, output);
156 printf("์๋ณธ ํฌ๊ธฐ: %llu ๋ฐ์ดํธ\n", (unsigned long long)file_size);
157 printf("ํค ํด์: 0x%08X\n", header.key_hash);
158
159 return 0;
160}
161
162/**
163 * ํ์ผ ๋ณตํธํ (ํค๋ ๊ฒ์ฆ ํฌํจ)
164 *
165 * @param input ์
๋ ฅ ํ์ผ ๊ฒฝ๋ก (์ํธํ๋ ํ์ผ)
166 * @param output ์ถ๋ ฅ ํ์ผ ๊ฒฝ๋ก (๋ณตํธํ๋ ํ์ผ)
167 * @param key ๋ณตํธํ ํค
168 * @return ์ฑ๊ณต ์ 0, ์คํจ ์ 1
169 */
170int decrypt_file(const char *input, const char *output, const char *key) {
171 // ์ํธํ๋ ํ์ผ ์ด๊ธฐ
172 FILE *fin = fopen(input, "rb");
173 if (!fin) {
174 perror("์
๋ ฅ ํ์ผ ์ด๊ธฐ ์คํจ");
175 return 1;
176 }
177
178 // ํค๋ ์ฝ๊ธฐ
179 FileHeader header;
180 if (fread(&header, sizeof(FileHeader), 1, fin) != 1) {
181 fprintf(stderr, "์ค๋ฅ: ์๋ชป๋ ์ํธํ ํ์ผ (ํค๋ ์ฝ๊ธฐ ์คํจ)\n");
182 fclose(fin);
183 return 1;
184 }
185
186 // ๋งค์ง ๋๋ฒ ํ์ธ (ํ์ผ์ด XENC ํ์์ธ์ง ๊ฒ์ฆ)
187 if (memcmp(header.magic, MAGIC, 4) != 0) {
188 fprintf(stderr, "์ค๋ฅ: ์ ํจํ ์ํธํ ํ์ผ์ด ์๋๋๋ค (๋งค์ง ๋๋ฒ ๋ถ์ผ์น)\n");
189 fprintf(stderr, "๊ธฐ๋๊ฐ: %.4s, ์ค์ ๊ฐ: %.4s\n", MAGIC, header.magic);
190 fclose(fin);
191 return 1;
192 }
193
194 // ๋ฒ์ ํ์ธ
195 if (header.version != VERSION) {
196 fprintf(stderr, "๊ฒฝ๊ณ : ํ์ผ ๋ฒ์ ์ด ๋ค๋ฆ
๋๋ค (๊ธฐ๋: %d, ์ค์ : %d)\n",
197 VERSION, header.version);
198 }
199
200 // ํค ๊ฒ์ฆ (ํด์ ๋น๊ต)
201 uint32_t input_key_hash = hash_key(key);
202 if (header.key_hash != input_key_hash) {
203 fprintf(stderr, "์ค๋ฅ: ์๋ชป๋ ๋น๋ฐ๋ฒํธ\n");
204 fprintf(stderr, "๊ธฐ๋ ํด์: 0x%08X, ์
๋ ฅ ํด์: 0x%08X\n",
205 header.key_hash, input_key_hash);
206 fclose(fin);
207 return 1;
208 }
209
210 // ์ถ๋ ฅ ํ์ผ ์ด๊ธฐ
211 FILE *fout = fopen(output, "wb");
212 if (!fout) {
213 perror("์ถ๋ ฅ ํ์ผ ์ด๊ธฐ ์คํจ");
214 fclose(fin);
215 return 1;
216 }
217
218 // ๋ฐ์ดํฐ ๋ณตํธํ
219 unsigned char buffer[BUFFER_SIZE];
220 size_t bytes_read;
221 size_t key_len = strlen(key);
222 size_t key_pos = 0; // ํค ์์น ์ถ์
223
224 printf("๋ณตํธํ ์ค...\n");
225 while ((bytes_read = fread(buffer, 1, BUFFER_SIZE, fin)) > 0) {
226 xor_buffer(buffer, bytes_read, key, key_len, &key_pos);
227 fwrite(buffer, 1, bytes_read, fout);
228
229 // ์งํ๋ฅ ํ์
230 printf(".");
231 fflush(stdout);
232 }
233 printf("\n");
234
235 fclose(fin);
236 fclose(fout);
237
238 printf("๋ณตํธํ ์๋ฃ: %s -> %s\n", input, output);
239 printf("์๋ณธ ํฌ๊ธฐ: %llu ๋ฐ์ดํธ\n", (unsigned long long)header.original_size);
240
241 return 0;
242}
243
244/**
245 * ์ํธํ ํ์ผ ์ ๋ณด ํ์
246 *
247 * @param filename ์ํธํ ํ์ผ ๊ฒฝ๋ก
248 * @return ์ฑ๊ณต ์ 0, ์คํจ ์ 1
249 */
250int show_info(const char *filename) {
251 FILE *fp = fopen(filename, "rb");
252 if (!fp) {
253 perror("ํ์ผ ์ด๊ธฐ ์คํจ");
254 return 1;
255 }
256
257 FileHeader header;
258 if (fread(&header, sizeof(FileHeader), 1, fp) != 1) {
259 fprintf(stderr, "์ค๋ฅ: ํค๋๋ฅผ ์ฝ์ ์ ์์ต๋๋ค\n");
260 fclose(fp);
261 return 1;
262 }
263
264 // ํ์ผ ์ ์ฒด ํฌ๊ธฐ ํ์ธ
265 fseek(fp, 0, SEEK_END);
266 long total_size = ftell(fp);
267 fclose(fp);
268
269 // ๋งค์ง ๋๋ฒ ํ์ธ
270 if (memcmp(header.magic, MAGIC, 4) != 0) {
271 printf("์ํธํ ํ์ผ์ด ์๋๋๋ค (XENC ๋งค์ง ๋๋ฒ ์์)\n");
272 return 1;
273 }
274
275 // ์ ๋ณด ์ถ๋ ฅ
276 printf("=== ์ํธํ ํ์ผ ์ ๋ณด ===\n");
277 printf("๋งค์ง ๋๋ฒ: %.4s\n", header.magic);
278 printf("๋ฒ์ : %d\n", header.version);
279 printf("ํค ํด์: 0x%08X\n", header.key_hash);
280 printf("์๋ณธ ํฌ๊ธฐ: %llu ๋ฐ์ดํธ\n", (unsigned long long)header.original_size);
281 printf("ํ์ผ ํฌ๊ธฐ: %ld ๋ฐ์ดํธ\n", total_size);
282 printf("ํค๋ ํฌ๊ธฐ: %lu ๋ฐ์ดํธ\n", sizeof(FileHeader));
283 printf("์ํธํ ๋ฐ์ดํฐ: %ld ๋ฐ์ดํธ\n", total_size - (long)sizeof(FileHeader));
284
285 return 0;
286}
287
288/**
289 * ๋ฉ์ธ ํจ์
290 */
291int main(int argc, char *argv[]) {
292 if (argc < 2) {
293 print_usage(argv[0]);
294 return 1;
295 }
296
297 // ๋ช
๋ น ๋ถ๊ธฐ
298 if (strcmp(argv[1], "encrypt") == 0) {
299 if (argc < 5) {
300 print_usage(argv[0]);
301 return 1;
302 }
303 return encrypt_file(argv[2], argv[3], argv[4]);
304 }
305 else if (strcmp(argv[1], "decrypt") == 0) {
306 if (argc < 5) {
307 print_usage(argv[0]);
308 return 1;
309 }
310 return decrypt_file(argv[2], argv[3], argv[4]);
311 }
312 else if (strcmp(argv[1], "info") == 0) {
313 if (argc < 3) {
314 print_usage(argv[0]);
315 return 1;
316 }
317 return show_info(argv[2]);
318 }
319 else {
320 fprintf(stderr, "์ค๋ฅ: ์ ์ ์๋ ๋ช
๋ น '%s'\n", argv[1]);
321 print_usage(argv[0]);
322 return 1;
323 }
324
325 return 0;
326}