【问题标题】:Compute the CBC-MAC with AES-256 and openssl in C在 C 中使用 AES-256 和 openssl 计算 CBC-MAC
【发布时间】:2017-12-10 09:36:51
【问题描述】:

我想用 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 

加密后的信息和命令行输出完全一样,除了最后一行全是0。我以为第一行是加密后的IV,后面三行是加密后的信息,所以以我的解释最后消息行未加密。但令我惊讶的是,解密结果与我用作输入的文本完全一致,因此似乎没有丢失信息。

问题:

  • 我怎么可能解密我的加密输出,即使我没有最后一行?
  • 什么是我的 CBC-MAC?它是我的命令行输出的最后一行还是我的 C 代码输出的最后一行?
  • 我的 C 代码有问题吗?我使用this so question 作为帮助。

【问题讨论】:

  • CBC-MAC 是各种坏的,没有单一的标准或普遍接受的 CBC-MAC 实现。 CMAC 是一个正确定义的标准,它提供比“CBC-MAC”(无论是什么)更好的安全性。如果您只需要 MAC,那么 HMAC-SHA256 可能是更好的选择。
  • CBC-MAC 对于所有输入都是不安全的,除了那些是密码块大小的倍数的输入。如果您想使用基于分组密码的 MAC,您应该使用 CMAC。 CMAC 是正确的 CBC-MAC。另请参阅 Matthew Green 的 Why I hate CBC-MAC

标签: c openssl cryptography aes cbc-mac


【解决方案1】:

你的错误在这里:

我有一个额外的块,因为第一个块应该是加密的 IV。

额外的块是因为 OpenSSL 在纯文本中添加了填充,因此它是块大小的倍数(AES 为 16 字节)。在这种情况下,纯文本已经是 16 字节的倍数,但使用的填充方案 (PKCS7)总是添加了填充,因此这里在加密之前添加了整个块。

通常将 IV 添加到密文的前面,但这不是这里发生的事情。

为了从您的代码中获得相同的结果,您需要自己添加此填充。在这种情况下它相当简单,只需在msg1 的末尾添加16 个0x10 字节(因此其总长度为64),并将48 调用中的AES_cbc_encrypt 更改为64。您看到的零只是您将 obuf 初始化为的值,因为您只将 48 个字节写入此缓冲区。

【讨论】:

  • 谢谢,现在可以了。您将加密的填充(最后一行)作为 CBC-MAC 还是之前的行?
  • @izlin 您将使用最后一个块。通常最后一个块包含填充和消息的混合,只有在消息长度恰好是块长度的倍数的情况下(如这里),最后一个块将仅填充。也可以看看blog.cryptographyengineering.com/2013/02/15/why-i-hate-cbc-mac
  • 好文章。我不想在任何应用程序中使用 CBC-MAC,它只是为了学习和理解。现在我至少可以肯定以后会更好地使用 HMAC。
猜你喜欢
  • 2013-08-11
  • 2022-08-17
  • 2017-08-28
  • 1970-01-01
  • 2014-09-11
  • 2023-02-23
  • 1970-01-01
  • 1970-01-01
  • 2019-04-14
相关资源
最近更新 更多