scramble.c (4963B)
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 #define MAXCHUNK (2048*1024) 5 6 static unsigned int seed; 7 8 void my_srand(unsigned int n) 9 { 10 seed = n & 0xffff; 11 } 12 13 unsigned int my_rand() 14 { 15 seed = (seed * 2109 + 9273) & 0x7fff; 16 return (seed + 0xc000) & 0xffff; 17 } 18 19 void load(FILE *fh, unsigned char *ptr, unsigned long sz) 20 { 21 if(fread(ptr, 1, sz, fh) != sz) 22 { 23 fprintf(stderr, "Read error!\n"); 24 exit(1); 25 } 26 } 27 28 void load_chunk(FILE *fh, unsigned char *ptr, unsigned long sz) 29 { 30 static int idx[MAXCHUNK/32]; 31 int i; 32 33 /* Convert chunk size to number of slices */ 34 sz /= 32; 35 36 /* Initialize index table with unity, 37 so that each slice gets loaded exactly once */ 38 for(i = 0; i < sz; i++) 39 idx[i] = i; 40 41 for(i = sz-1; i >= 0; --i) 42 { 43 /* Select a replacement index */ 44 int x = (my_rand() * i) >> 16; 45 46 /* Swap */ 47 int tmp = idx[i]; 48 idx[i] = idx[x]; 49 idx[x] = tmp; 50 51 /* Load resulting slice */ 52 load(fh, ptr+32*idx[i], 32); 53 } 54 } 55 56 void load_file(FILE *fh, unsigned char *ptr, unsigned long filesz) 57 { 58 unsigned long chunksz; 59 60 my_srand(filesz); 61 62 /* Descramble 2 meg blocks for as long as possible, then 63 gradually reduce the window down to 32 bytes (1 slice) */ 64 for(chunksz = MAXCHUNK; chunksz >= 32; chunksz >>= 1) 65 while(filesz >= chunksz) 66 { 67 load_chunk(fh, ptr, chunksz); 68 filesz -= chunksz; 69 ptr += chunksz; 70 } 71 72 /* Load final incomplete slice */ 73 if(filesz) 74 load(fh, ptr, filesz); 75 } 76 77 void read_file(char *filename, unsigned char **ptr, unsigned long *sz) 78 { 79 FILE *fh = fopen(filename, "rb"); 80 if(fh == NULL) 81 { 82 fprintf(stderr, "Can't open \"%s\".\n", filename); 83 exit(1); 84 } 85 if(fseek(fh, 0, SEEK_END)<0) 86 { 87 fprintf(stderr, "Seek error.\n"); 88 exit(1); 89 } 90 *sz = ftell(fh); 91 *ptr = malloc(*sz); 92 if( *ptr == NULL ) 93 { 94 fprintf(stderr, "Out of memory.\n"); 95 exit(1); 96 } 97 if(fseek(fh, 0, SEEK_SET)<0) 98 { 99 fprintf(stderr, "Seek error.\n"); 100 exit(1); 101 } 102 load_file(fh, *ptr, *sz); 103 fclose(fh); 104 } 105 106 void save(FILE *fh, unsigned char *ptr, unsigned long sz) 107 { 108 if(fwrite(ptr, 1, sz, fh) != sz) 109 { 110 fprintf(stderr, "Write error!\n"); 111 exit(1); 112 } 113 } 114 115 void save_chunk(FILE *fh, unsigned char *ptr, unsigned long sz) 116 { 117 static int idx[MAXCHUNK/32]; 118 int i; 119 120 /* Convert chunk size to number of slices */ 121 sz /= 32; 122 123 /* Initialize index table with unity, 124 so that each slice gets saved exactly once */ 125 for(i = 0; i < sz; i++) 126 idx[i] = i; 127 128 for(i = sz-1; i >= 0; --i) 129 { 130 /* Select a replacement index */ 131 int x = (my_rand() * i) >> 16; 132 133 /* Swap */ 134 int tmp = idx[i]; 135 idx[i] = idx[x]; 136 idx[x] = tmp; 137 138 /* Save resulting slice */ 139 save(fh, ptr+32*idx[i], 32); 140 } 141 } 142 143 void save_file(FILE *fh, unsigned char *ptr, unsigned long filesz) 144 { 145 unsigned long chunksz; 146 147 my_srand(filesz); 148 149 /* Descramble 2 meg blocks for as long as possible, then 150 gradually reduce the window down to 32 bytes (1 slice) */ 151 for(chunksz = MAXCHUNK; chunksz >= 32; chunksz >>= 1) 152 while(filesz >= chunksz) 153 { 154 save_chunk(fh, ptr, chunksz); 155 filesz -= chunksz; 156 ptr += chunksz; 157 } 158 159 /* Save final incomplete slice */ 160 if(filesz) 161 save(fh, ptr, filesz); 162 } 163 164 void write_file(char *filename, unsigned char *ptr, unsigned long sz) 165 { 166 FILE *fh = fopen(filename, "wb"); 167 if(fh == NULL) 168 { 169 fprintf(stderr, "Can't open \"%s\".\n", filename); 170 exit(1); 171 } 172 save_file(fh, ptr, sz); 173 fclose(fh); 174 } 175 176 void descramble(char *src, char *dst) 177 { 178 unsigned char *ptr = NULL; 179 unsigned long sz = 0; 180 FILE *fh; 181 182 read_file(src, &ptr, &sz); 183 184 fh = fopen(dst, "wb"); 185 if(fh == NULL) 186 { 187 fprintf(stderr, "Can't open \"%s\".\n", dst); 188 exit(1); 189 } 190 if( fwrite(ptr, 1, sz, fh) != sz ) 191 { 192 fprintf(stderr, "Write error.\n"); 193 exit(1); 194 } 195 fclose(fh); 196 free(ptr); 197 } 198 199 void scramble(char *src, char *dst) 200 { 201 unsigned char *ptr = NULL; 202 unsigned long sz = 0; 203 FILE *fh; 204 205 fh = fopen(src, "rb"); 206 if(fh == NULL) 207 { 208 fprintf(stderr, "Can't open \"%s\".\n", src); 209 exit(1); 210 } 211 if(fseek(fh, 0, SEEK_END)<0) 212 { 213 fprintf(stderr, "Seek error.\n"); 214 exit(1); 215 } 216 sz = ftell(fh); 217 ptr = malloc(sz); 218 if( ptr == NULL ) 219 { 220 fprintf(stderr, "Out of memory.\n"); 221 exit(1); 222 } 223 if(fseek(fh, 0, SEEK_SET)<0) 224 { 225 fprintf(stderr, "Seek error.\n"); 226 exit(1); 227 } 228 if( fread(ptr, 1, sz, fh) != sz ) 229 { 230 fprintf(stderr, "Read error.\n"); 231 exit(1); 232 } 233 fclose(fh); 234 235 write_file(dst, ptr, sz); 236 237 free(ptr); 238 } 239 240 int main(int argc, char *argv[]) 241 { 242 int opt = 0; 243 244 if(argc > 1 && !strcmp(argv[1], "-d")) 245 opt ++; 246 247 if(argc != 3+opt) 248 { 249 fprintf(stderr, "Usage: %s [-d] from to\n", argv[0]); 250 exit(1); 251 } 252 253 if(opt) 254 descramble(argv[2], argv[3]); 255 else 256 scramble(argv[1], argv[2]); 257 258 return 0; 259 }