我正在编写一个保险丝文件系统,我有一个问题。
我正在使用CBC AES加密磁盘中的数据。问题是填充。当密码大小例如是15个字节时,没有问题,因为它增加了1个字节。问题是,当我试图加密4096字节时,它还增加了我16字节的padd,它对我来说是失败的。我不知道它为什么添加填充因为4096是128(size aes block)的倍数。我需要修改我的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;
}
答案 0 :(得分:3)
见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
答案 1 :(得分:0)
问题在于,当我尝试加密4096字节时,它还会增加16字节的padd,这对我来说是失败的。我不知道它为什么添加填充因为4096是128(size aes block)的倍数。
正如Zaph所述,正在添加PKCS#7填充。填充是确定性的,因此也填充16个字节的精确倍数以确保移除。否则,广义算法如何知道何时(1)纯文本在16字节边界上结束,而(2)纯文本不在16字节边界上结束并填充?
您可以使用EVP_CIPHER_CTX_ctrl
和EVP_CIPHER_CTX_set_padding
禁用密码对象的填充行为。 EVP_CIPHER_CTX_set_padding
是EVP_CIPHER_CTX_ctrl
的宏观版本。这是它的样子:
int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *x, int padding);
从手册页:
EVP_CIPHER_CTX_set_padding()启用或禁用填充。默认情况下 加密操作使用标准块填充和填充 在解密时检查并删除填充。如果是pad参数 为零,则不执行填充,即数据总量 加密或解密必须是块大小的倍数或 会发生错误。
我知道如果明文不是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);