📄 aesxam.cpp
字号:
if(rlen > 0 && rlen < BLOCK_LEN)
{
// move the previous ciphertext to top half of double buffer
// since rlen bytes of this are output last
for(i = 0; i < BLOCK_LEN; ++i)
dbuf[i + BLOCK_LEN] = dbuf[i];
// read last part of plaintext into bottom half of buffer
if(fread(dbuf, 1, rlen, fin) != rlen)
return READ_ERROR;
// clear the remainder of the bottom half of buffer
for(i = 0; i < BLOCK_LEN - rlen; ++i)
dbuf[rlen + i] = 0;
// do CBC chaining from previous ciphertext
for(i = 0; i < BLOCK_LEN; ++i)
dbuf[i] ^= dbuf[i + BLOCK_LEN];
// encrypt the final block
aes_enc_blk((unsigned char*)(char const*)dbuf, (unsigned char*)dbuf, ctx);
// set the length of the final write
len = rlen + BLOCK_LEN; rlen = 0;
}
// write the encrypted block
if(fwrite(dbuf, 1, len, fout) != len)
return WRITE_ERROR;
}
}
return 0;
}
int decfile(FILE *fin, FILE *fout, aes_ctx *ctx, const char* ifn, const char* ofn)
{ char buf1[BLOCK_LEN], buf2[BLOCK_LEN], dbuf[2 * BLOCK_LEN];
char *b1, *b2, *bt;
fpos_t flen;
unsigned long i, len, rlen;
// find the file length
fseek(fin, 0, SEEK_END);
fgetpos(fin, &flen);
rlen = file_len(flen);
// reset to start
fseek(fin, 0, SEEK_SET);
if(rlen <= 2 * BLOCK_LEN)
{ // if the original file length is less than or equal to 16 bytes
// read the bytes of the file and verify length
len = (unsigned long)fread(dbuf, 1, 2 * BLOCK_LEN, fin);
rlen -= len;
if(rlen > 0)
return READ_ERROR;
// set the original file length
len -= BLOCK_LEN;
// decrypt from position len to position len + BLOCK_LEN
aes_dec_blk((unsigned char*)(char const*)(dbuf + len), (unsigned char*)(dbuf + BLOCK_LEN), ctx);
// undo CBC chaining
for(i = 0; i < len; ++i)
dbuf[i] ^= dbuf[i + BLOCK_LEN];
// output decrypted bytes
if(fwrite(dbuf, 1, len, fout) != len)
return WRITE_ERROR;
}
else
{ // we need two input buffers because we have to keep the previous
// ciphertext block - the pointers b1 and b2 are swapped once per
// loop so that b2 points to new ciphertext block and b1 to the
// last ciphertext block
rlen -= BLOCK_LEN; b1 = buf1; b2 = buf2;
// input the IV
if(fread(b1, 1, BLOCK_LEN, fin) != BLOCK_LEN)
return READ_ERROR;
// read the encrypted file a block at a time
while(rlen > 0 && !feof(fin))
{
// input a block and reduce the remaining byte count
len = (unsigned long)fread(b2, 1, BLOCK_LEN, fin);
rlen -= len;
// verify the length of the read operation
if(len != BLOCK_LEN)
return READ_ERROR;
// decrypt input buffer
aes_dec_blk((unsigned char*)(char const*)b2, (unsigned char*)dbuf, ctx);
// if there is only one more block do ciphertext stealing
if(rlen > 0 && rlen < BLOCK_LEN)
{
// read last ciphertext block
if(fread(b2, 1, rlen, fin) != rlen)
return READ_ERROR;
// append high part of last decrypted block
for(i = rlen; i < BLOCK_LEN; ++i)
b2[i] = dbuf[i];
// decrypt last block of plaintext
for(i = 0; i < rlen; ++i)
dbuf[i + BLOCK_LEN] = dbuf[i] ^ b2[i];
// decrypt last but one block of plaintext
aes_dec_blk((unsigned char*)(char const*)b2, (unsigned char*)dbuf, ctx);
// adjust length of last output block
len = rlen + BLOCK_LEN; rlen = 0;
}
// unchain CBC using the last ciphertext block
for(i = 0; i < BLOCK_LEN; ++i)
dbuf[i] ^= b1[i];
// write decrypted block
if(fwrite(dbuf, 1, len, fout) != len)
return WRITE_ERROR;
// swap the buffer pointers
bt = b1, b1 = b2, b2 = bt;
}
}
return 0;
}
int main(int argc, char *argv[])
{ FILE *fin = 0, *fout = 0;
char *cp, ch, key[32];
int i, by, key_len, err = 0;
aes_ctx ctx[1];
if(argc != 5 || toupper(*argv[3]) != 'D' && toupper(*argv[3]) != 'E')
{
printf("usage: aesxam in_filename out_filename [d/e] key_in_hex\n");
err = -1; goto exit;
}
ctx->n_rnd = 0; // ensure all flags are initially set to zero
ctx->n_blk = 0;
cp = argv[4]; // this is a pointer to the hexadecimal key digits
i = 0; // this is a count for the input digits processed
while(i < 64 && *cp) // the maximum key length is 32 bytes and
{ // hence at most 64 hexadecimal digits
ch = toupper(*cp++); // process a hexadecimal digit
if(ch >= '0' && ch <= '9')
by = (by << 4) + ch - '0';
else if(ch >= 'A' && ch <= 'F')
by = (by << 4) + ch - 'A' + 10;
else // error if not hexadecimal
{
printf("key must be in hexadecimal notation\n");
err = -2; goto exit;
}
// store a key byte for each pair of hexadecimal digits
if(i++ & 1)
key[i / 2 - 1] = by & 0xff;
}
if(*cp)
{
printf("The key value is too long\n");
err = -3; goto exit;
}
else if(i < 32 || (i & 15))
{
printf("The key length must be 32, 48 or 64 hexadecimal digits\n");
err = -4; goto exit;
}
key_len = i / 2;
if(!(fin = fopen(argv[1], "rb"))) // try to open the input file
{
printf("The input file: %s could not be opened\n", argv[1]);
err = -5; goto exit;
}
if(!(fout = fopen(argv[2], "wb"))) // try to open the output file
{
printf("The input file: %s could not be opened\n", argv[1]);
err = -6; goto exit;
}
if(toupper(*argv[3]) == 'E') // encryption in Cipher Block Chaining mode
{
aes_enc_key((unsigned char*)(char const*)key, key_len, ctx);
err = encfile(fin, fout, ctx, argv[1], argv[2]);
}
else // decryption in Cipher Block Chaining mode
{
aes_dec_key((unsigned char*)(char const*)key, key_len, ctx);
err = decfile(fin, fout, ctx, argv[1], argv[2]);
}
exit:
if(err == READ_ERROR)
printf("Error reading from input file: %s\n", argv[1]);
if(err == WRITE_ERROR)
printf("Error writing to output file: %s\n", argv[2]);
if(fout)
fclose(fout);
if(fin)
fclose(fin);
return err;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -