📄 aesxam.c
字号:
// encrypt the block (now in b1)
aes_encrypt(b1, b1, ctx);
if(len != 0 && len != BLOCK_LEN) // use ciphertext stealing
{
// set the length of the last block
wlen = len;
// xor ciphertext into last block
for(i = 0; i < len; ++i)
b3[i] ^= b1[i];
// move 'stolen' ciphertext into last block
for(i = len; i < BLOCK_LEN; ++i)
b3[i] = b1[i];
// encrypt this block
aes_encrypt(b3, b3, ctx);
// and write it as the second to last encrypted block
if(fwrite((char*)b3, 1, BLOCK_LEN, fout) != BLOCK_LEN)
return WRITE_ERROR;
}
// write the encrypted block
if(fwrite((char*)b1, 1, wlen, fout) != wlen)
return WRITE_ERROR;
if(len != BLOCK_LEN)
return OK;
// advance the buffer pointers
bt = b3, b3 = b2, b2 = b1, b1 = bt;
}
}
}
int decfile(FILE *fin, FILE *fout, aes_decrypt_ctx ctx[1])
{ unsigned char dbuf[3 * BLOCK_LEN], buf[BLOCK_LEN];
unsigned long i, len, wlen = BLOCK_LEN;
// When ciphertext stealing is used, we three ciphertext blocks so
// we use a buffer that is three times the block length. The buffer
// pointers b1, b2 and b3 point to the buffer positions of three
// ciphertext blocks, b3 being the most recent and b1 being the
// oldest. We start with the IV in b1 and the block to be decrypted
// in b2.
len = (unsigned long)fread((char*)dbuf, 1, 2 * BLOCK_LEN, fin);
if(len < 2 * BLOCK_LEN) // the original file is less than one block in length
{
len -= BLOCK_LEN;
// decrypt from position len to position len + BLOCK_LEN
aes_decrypt(dbuf + len, dbuf + len, ctx);
// undo the CBC chaining
for(i = 0; i < len; ++i)
dbuf[i] ^= dbuf[i + BLOCK_LEN];
// output the decrypted bytes
if(fwrite((char*)dbuf, 1, len, fout) != len)
return WRITE_ERROR;
return OK;
}
else
{ unsigned char *b1 = dbuf, *b2 = b1 + BLOCK_LEN, *b3 = b2 + BLOCK_LEN, *bt;
for( ; ; ) // while some ciphertext remains, prepare to decrypt block b2
{
// read in the next block to see if ciphertext stealing is needed
len = fread((char*)b3, 1, BLOCK_LEN, fin);
// decrypt the b2 block
aes_decrypt(b2, buf, ctx);
if(len == 0 || len == BLOCK_LEN) // no ciphertext stealing
{
// unchain CBC using the previous ciphertext block in b1
for(i = 0; i < BLOCK_LEN; ++i)
buf[i] ^= b1[i];
}
else // partial last block - use ciphertext stealing
{
wlen = len;
// produce last 'len' bytes of plaintext by xoring with
// the lowest 'len' bytes of next block b3 - C[N-1]
for(i = 0; i < len; ++i)
buf[i] ^= b3[i];
// reconstruct the C[N-1] block in b3 by adding in the
// last (BLOCK_LEN - len) bytes of C[N-2] in b2
for(i = len; i < BLOCK_LEN; ++i)
b3[i] = buf[i];
// decrypt the C[N-1] block in b3
aes_decrypt(b3, b3, ctx);
// produce the last but one plaintext block by xoring with
// the last but two ciphertext block
for(i = 0; i < BLOCK_LEN; ++i)
b3[i] ^= b1[i];
// write decrypted plaintext blocks
if(fwrite((char*)b3, 1, BLOCK_LEN, fout) != BLOCK_LEN)
return WRITE_ERROR;
}
// write the decrypted plaintext block
if(fwrite((char*)buf, 1, wlen, fout) != wlen)
return WRITE_ERROR;
if(len != BLOCK_LEN)
return OK;
// advance the buffer pointers
bt = b1, b1 = b2, b2 = b3, b3 = bt;
}
}
}
int main(int argc, char *argv[])
{ FILE *fin = 0, *fout = 0;
char *cp, ch, key[32];
int i, by = 0, key_len, err = 0;
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;
}
aes_init(); // in case dynamic AES tables are being used
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 output file: %s could not be opened\n", argv[2]);
err = -6; goto exit;
}
if(toupper(*argv[3]) == 'E') // encryption in Cipher Block Chaining mode
{ aes_encrypt_ctx ctx[1];
aes_encrypt_key((unsigned char*)key, key_len, ctx);
err = encfile(fin, fout, ctx);
}
else // decryption in Cipher Block Chaining mode
{ aes_decrypt_ctx ctx[1];
aes_decrypt_key((unsigned char*)key, key_len, ctx);
err = decfile(fin, fout, ctx);
}
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 + -