-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathencrypt.c
194 lines (174 loc) · 5.19 KB
/
encrypt.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
/*
* This code encrypts input data using the Rijndael (AES) cipher. The
* key length is hard-coded to 128 key bits; this number may be changed
* by redefining a constant near the start of the file.
*
* This program uses CTR mode encryption.
*
* Usage: encrypt <key1> <key2> <file name>
*
* Author: Ethan L. Miller ([email protected])
* Based on code from Philip J. Erdelsky ([email protected])
*
*/
#include <stdio.h>
#include <fcntl.h>
#include <strings.h>
#include <unistd.h>
#include <stdlib.h>
#include "rijndael.h"
static char rcsid[] = "$Id: encrypt.c,v 1.2 2003/04/15 01:05:36 elm Exp elm $";
#define KEYBITS 128
/***********************************************************************
*
* hexvalue
*
* This routine takes a single character as input, and returns the
* hexadecimal equivalent. If the character passed isn't a hex value,
* the program exits.
*
***********************************************************************
*/
int hexvalue (char c)
{
if (c >= '0' && c <= '9') {
return (c - '0');
} else if (c >= 'a' && c <= 'f') {
return (10 + c - 'a');
} else if (c >= 'A' && c <= 'F') {
return (10 + c - 'A');
} else {
fprintf (stderr, "ERROR: key digit %c isn't a hex digit!\n", c);
exit (-1);
}
}
/***********************************************************************
*
* getpassword
*
* Get the key from the password. The key is specified as a string of
* hex digits, two per key byte. password points at the character
* currently being added to the key. If it's '\0', the key is done.
*
***********************************************************************
*/
void
getpassword (const char *password, unsigned char *key, int keylen)
{
int i;
for (i = 0; i < keylen; i++) {
if (*password == '\0') {
key[i] = 0;
} else {
/* Add the first of two digits to the current key value */
key[i] = hexvalue (*(password++)) << 4;
/* If there's a second digit at this position, add it */
if (*password != '\0') {
key[i] |= hexvalue (*(password++));
}
}
}
}
int main(int argc, char **argv)
{
unsigned long rk[RKLENGTH(KEYBITS)]; /* round key */
unsigned char key[KEYLENGTH(KEYBITS)]; /* cipher key */
char buf[100];
int i, nbytes, nwritten , ctr;
int totalbytes;
int k0, k1;
int fileId = 0x1234;
int nrounds; /* # of Rijndael rounds */
char *password; /* supplied (ASCII) password */
int fd;
char *filename;
unsigned char filedata[16];
unsigned char ciphertext[16];
unsigned char ctrvalue[16];
#if 0
if (argc < 3)
{
fprintf (stderr, "Usage: %s <key> <file>\n", argv[0]);
return 1;
}
/*
* Get the key from the password. The key is specified as a string of
* hex digits, two per key byte. password points at the character
* currently being added to the key. If it's '\0', the key is done.
*/
getpassword (argv[1], key, sizeof (key));
filename = argv[2];
#else
if (argc < 4)
{
fprintf (stderr, "Usage: %s <key1> <key2> <file>\n", argv[0]);
return 1;
}
bzero (key, sizeof (key));
k0 = strtol (argv[1], NULL, 0);
k1 = strtol (argv[2], NULL, 0);
bcopy (&k0, &(key[0]), sizeof (k0));
bcopy (&k1, &(key[sizeof(k0)]), sizeof (k1));
filename = argv[3];
#endif
/* Print the key, just in case */
for (i = 0; i < sizeof (key); i++) {
sprintf (buf+2*i, "%02x", key[sizeof(key)-i-1]);
}
fprintf (stderr, "KEY: %s\n", buf);
/*
* Initialize the Rijndael algorithm. The round key is initialized by this
* call from the values passed in key and KEYBITS.
*/
nrounds = rijndaelSetupEncrypt(rk, key, KEYBITS);
/*
* Open the file.
*/
fd = open(filename, O_RDWR);
if (fd < 0)
{
fprintf(stderr, "Error opening file %s\n", argv[2]);
return 1;
}
/* fileID goes into bytes 8-11 of the ctrvalue */
bcopy (&fileId, &(ctrvalue[8]), sizeof (fileId));
/* This loop reads 16 bytes from the file, XORs it with the encrypted
CTR value, and then writes it back to the file at the same position.
Note that CTR encryption is nice because the same algorithm does
encryption and decryption. In other words, if you run this program
twice, it will first encrypt and then decrypt the file.
*/
for (ctr = 0, totalbytes = 0; /* loop forever */; ctr++)
{
/* Read 16 bytes (128 bits, the blocksize) from the file */
nbytes = read (fd, filedata, sizeof (filedata));
if (nbytes <= 0) {
break;
}
if (lseek (fd, totalbytes, SEEK_SET) < 0)
{
perror ("Unable to seek back over buffer");
exit (-1);
}
/* Set up the CTR value to be encrypted */
bcopy (&ctr, &(ctrvalue[0]), sizeof (ctr));
/* Call the encryption routine to encrypt the CTR value */
rijndaelEncrypt(rk, nrounds, ctrvalue, ciphertext);
/* XOR the result into the file data */
for (i = 0; i < nbytes; i++) {
filedata[i] ^= ciphertext[i];
}
/* Write the result back to the file */
nwritten = write(fd, filedata, nbytes);
if (nwritten != nbytes)
{
fprintf (stderr,
"%s: error writing the file (expected %d, got %d at ctr %d\n)",
argv[0], nbytes, nwritten, ctr);
break;
}
/* Increment the total bytes written */
totalbytes += nbytes;
}
close (fd);
}