我想用 openssl 计算给定明文的 CBC-MAC。我有以下明文(hexdump):
hexdump -C example.txt
00000000 4d 41 43 73 20 61 72 65 20 76 65 72 79 20 75 73 |MACs are very us|
00000010 65 66 75 6c 20 69 6e 20 63 72 79 70 74 6f 67 72 |eful in cryptogr|
00000020 61 70 68 79 21 20 20 20 20 20 20 20 20 20 20 20 |aphy! |
如果我使用 openssl 的命令行功能,我会得到以下解决方案:
openssl aes-256-cbc -in example.txt -K 8000000000000000000000000000000000000000000000000000000000000001 -e -iv 00 | hexdump -C
00000000 e8 e9 a4 ce 5d 20 c4 ad f5 52 b2 c6 38 2e 12 4e |....] ...R..8..N|
00000010 20 f5 63 65 b4 b3 96 9f ad 8d ca e4 e8 34 2a e5 | .ce.........4*.|
00000020 0d 82 0e 3a 1e 10 5d 30 72 16 fc 00 c7 a5 b4 49 |...:..]0r......I|
00000030 f5 63 9f 85 ff e3 a4 a4 23 6e 6f 09 20 ed b1 ae |.c......#no. ...|
到现在为止还挺好。我有一个额外的块,因为第一个块应该是加密的 IV。现在最后一行应该是我的 CBC-MAC,如果我理解正确的话。接下来我尝试在 C 中做同样的事情,这里是示例代码:
#include <stdio.h>
#include <string.h>
#include <openssl/sha.h>
#include <openssl/aes.h>
int main(int argc, char *argv[])
{
unsigned char obuf[64] = {0};
unsigned char decbuf[48] = {0};
unsigned char msg1[] = {0x4d, 0x41, 0x43, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x76, 0x65, 0x72, 0x79, 0x20, 0x75, 0x73,
0x65, 0x66, 0x75, 0x6c, 0x20, 0x69, 0x6e, 0x20, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x67, 0x72,
0x61, 0x70, 0x68, 0x79, 0x21, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20};
unsigned char key[] = {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
unsigned char ivenc[] ={0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
unsigned char ivdec[] ={0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
int i=0;
AES_KEY enc_key, dec_key;
AES_set_encrypt_key(key, 256, &enc_key);
AES_cbc_encrypt(msg1, obuf, 48, &enc_key, ivenc, AES_ENCRYPT);
for (i = 0; i < 64; i++) {
if (!(i%16))
printf("\n");
printf("%02x ", obuf[i]);
}
printf("\n");
AES_set_decrypt_key(key, 256, &dec_key);
AES_cbc_encrypt(obuf, decbuf, 64, &dec_key, ivdec, AES_DECRYPT);
for (i = 0; i < 48; i++) {
if (!(i%16))
printf("\n");
printf("%02x ", decbuf[i]);
}
printf("\n");
return 0;
}
之后我解密加密的消息以验证我的代码。我的代码输出非常令人惊讶:
e8 e9 a4 ce 5d 20 c4 ad f5 52 b2 c6 38 2e 12 4e
20 f5 63 65 b4 b3 96 9f ad 8d ca e4 e8 34 2a e5
0d 82 0e 3a 1e 10 5d 30 72 16 fc 00 c7 a5 b4 49
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
4d 41 43 73 20 61 72 65 20 76 65 72 79 20 75 73
65 66 75 6c 20 69 6e 20 63 72 79 70 74 6f 67 72
61 70 68 79 21 20 20 20 20 20 20 20 20 20 20 20
The encrypted message is completely identical to the command line output, except the last line is all 0. I thought, that the first line is the encrypted IV and the three following lines are the encrypted message, so with my interpretation the last line of the message wasn't encrypted. But to my surprise the decryption results exactly to the text I used as input, so it seems that there is no loss of information.
Questions:
- How is it possible that I can decrypt the output of my encryption, even if I don't have the last line?
- What is my CBC-MAC? is it the last line from my command line output or the last line of my C-code output?
- Am I doing something wrong in my C code? I used this so question as help.