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
| #include <stdio.h> #include <string.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <stdlib.h>
#define ROUNDS 20 #define ROTL(a,b) (((a) << (b)) | ((a) >> (32 - (b)))) #define QR(a,b,c,d)( \ a += b, d ^= a, d = ROTL(d,16), \ c += d, b ^= c, b = ROTL(b,12), \ a += b, d ^= a, d = ROTL(d,8), \ c += d, b ^= c, b = ROTL(b,7) \ )
static const char Const[4] = "CONS"; static const char iv[2] = "iv"; u_int32_t tmpinit[16];
void chacha20_ivinit(char *key){ int i; unsigned char *k = (unsigned char *) key; for (i = 0; i < 4; i++) tmpinit[i] = (u_int32_t) Const[i]; for (i = 4; i < 12; i++) tmpinit[i] = (u_int32_t) k[i - 4]; tmpinit[12] = tmpinit[13] = 0; tmpinit[14] = (u_int32_t) iv[0]; tmpinit[15] = (u_int32_t) iv[1]; }
void chacha20(char *data, int group_id) { char *a = (char *)data; u_int32_t tmp[16]; int i; for (i = 0; i < 16; i++) tmp[i] = tmpinit[i];
for (i = 0; i < ROUNDS; i += 2){ QR(tmp[0], tmp[4], tmp[8], tmp[12]); QR(tmp[1], tmp[5], tmp[9], tmp[13]); QR(tmp[2], tmp[6], tmp[10], tmp[14]); QR(tmp[3], tmp[7], tmp[11], tmp[15]); QR(tmp[0], tmp[5], tmp[10], tmp[15]); QR(tmp[1], tmp[6], tmp[11], tmp[12]); QR(tmp[2], tmp[7], tmp[8], tmp[13]); QR(tmp[3], tmp[4], tmp[9], tmp[14]); }
for (i = 0; i < 16; i++) { tmp[i] += tmpinit[i]; a[i + 16 * group_id] ^= (char) tmp[i]; } tmpinit[12] += 1; tmpinit[13] += 1; }
int main(int argc, char *argv[]) { int in_fd, out_fd; int group_id = 0; int b_size; char *b;
if (argc<4) { printf("Usage: ./encrypt {input_file} {output_file} {your_key(length=8)}"); } in_fd = open(argv[1], O_RDONLY); out_fd = open(argv[2], O_RDWR | O_CREAT); if (strlen(argv[3]) !=8){ printf("Sorry, the key length must be 8..."); exit(0); } if (in_fd != -1) { struct stat s; fstat(in_fd, &s); b_size = (s.st_size + 15) / 16 * 16; b = malloc(b_size); read(in_fd, b, s.st_size); chacha20_ivinit(argv[3]); for (int i = 0; i < b_size / 16; i++){ chacha20(b, i); } write(out_fd, b, s.st_size); close(in_fd); close(out_fd); } }
|