【问题标题】:Disable PKCS#7 padding on an AES cipher object? [duplicate]在 AES 密码对象上禁用 PKCS#7 填充? [复制]
【发布时间】:2016-10-30 12:14:11
【问题描述】:

我正在编写一个 fuse 文件系统,但我遇到了一个问题。

我正在使用 CBC AES 对磁盘中的数据进行加密。问题是填充。例如,当要加密的大小为 15 个字节时,这没有问题,因为它额外增加了 1 个字节。问题是,当我尝试加密 4096 个字节时,它还会给我添加 16 个字节的填充,这对我来说是失败的。我不知道为什么要添加填充,因为 4096 是 128 的倍数(大小 aes 块)。我需要修改我的 c 代码,以便对 openssl 说,仅在必要时添加填充,但并非总是如此......

我知道如果明文不是 128 的倍数,它将添加填充。但如果不是,为什么?我能做什么?

这是我的密码:

    int encrypt_data(unsigned char *plaintext, int plaintext_len, unsigned char *key,
                unsigned char *iv, unsigned char *ciphertext, int algorithm_pos)
{
        EVP_CIPHER_CTX *ctx;

        int len;

        int ciphertext_len;

        /* Create and initialise the context */
        if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors();

        /* Initialise the encryption operation. IMPORTANT - ensure you use a key
         * and IV size appropriate for your cipher
         * In this example we are using 256 bit AES (i.e. a 256 bit key). The
         * IV size for *most* modes is the same as the block size. For AES this
         * is 128 bits */
        if(1 != EVP_EncryptInit_ex(ctx, ciphers[algorithm_pos].algorithm(), NULL, key, iv))
                handleErrors();

        /* Provide the message to be encrypted, and obtain the encrypted output.
         * EVP_EncryptUpdate can be called multiple times if necessary
         */
        if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
                handleErrors();
        ciphertext_len = len;

        /* Finalise the encryption. Further ciphertext bytes may be written at
         * this stage.
         */
        if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) handleErrors();
        ciphertext_len += len;

        /* Clean up */
        EVP_CIPHER_CTX_free(ctx);

        return ciphertext_len;
}

【问题讨论】:

  • CBC 模式只提供机密性,您通常必须添加 MAC 才能安全地使用 CBC 模式。您可能应该使用经过身份验证的加密,因为它提供 机密性和真实性。请参阅 OpenSSL wiki 上的 EVP Authenticated Encryption and Decryption

标签: c encryption openssl aes pkcs#7


【解决方案1】:

PKCS#7 padding。填充块大小的精确倍数的原因是无法判断是否没有填充,因此必须始终或从不使用填充。考虑数据是否为 ​​4096 字节,最后一个字节为 0x01。看起来像一个字节的填充,但它不是,它是数据的一部分。

但您应该使用磁盘扇区加密模式,例如 XTS,XTS 仅推荐用于全磁盘加密。这就是 IEEE 标准 1619 的设计目的。

Explanation of the XTS Encryption Mode

还有 NIST:The XTS-AES Mode for Confidentiality on Storage Devices

【讨论】:

    【解决方案2】:

    问题是,当我尝试加密 4096 个字节时,它还会给我添加 16 个字节的填充,这对我来说是失败的。我不知道为什么要添加填充,因为 4096 是 128 的倍数(大小 aes 块)。

    正如 Zaph 所说,正在添加 PKCS#7 填充。填充是确定性的,因此还填充了 16 个字节的精确倍数以确保删除。否则,通用算法如何知道 (1) 纯文本何时以 16 字节边界结束,而 (2) 纯文本 not 何时以 16 字节边界结束并填充?

    您可以使用EVP_CIPHER_CTX_ctrlEVP_CIPHER_CTX_set_padding 禁用密码对象的填充行为。 EVP_CIPHER_CTX_set_paddingEVP_CIPHER_CTX_ctrl 的宏版本。这是它的样子:

    int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *x, int padding);
    

    来自手册页:

    EVP_CIPHER_CTX_set_padding() 启用或禁用填充。默认情况下 加密操作使用标准块填充和 解密时检查并删除填充。如果焊盘参数 为零则不执行填充,数据总量 然后加密或解密必须是块大小的倍数或 会发生错误。


    我知道如果明文不是 128 的倍数,它将添加填充。但如果不是,为什么?我能做什么?

    禁用密码上下文对象的填充。以下是图书馆的做法:

    $ grep -IR EVP_CIPHER_CTX_set_padding *
    CHANGES:  *) New function EVP_CIPHER_CTX_set_padding() this is used to
    apps/enc.c:            EVP_CIPHER_CTX_set_padding(ctx, 0);
    apps/speed.c:                EVP_CIPHER_CTX_set_padding(&ctx, 0);
    crypto/cms/cms_pwri.c:    EVP_CIPHER_CTX_set_padding(&kekctx, 0);
    crypto/evp/evp.h:int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *c, int pad);
    crypto/evp/evp_enc.c:int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *ctx, int pad)
    crypto/evp/evp_test.c:        EVP_CIPHER_CTX_set_padding(&ctx, 0);
    crypto/evp/evp_test.c:        EVP_CIPHER_CTX_set_padding(&ctx, 0);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-14
      • 2017-05-05
      • 2013-09-10
      • 1970-01-01
      相关资源
      最近更新 更多