2016-10-30 31 views
1

我正在编程保险丝文件系统,我有一个问题。禁用AES密码对象上的PKCS#7填充?

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

CBC模式只提供保密性,你通常要添加MAC安全使用CBC模式。您应该使用经过身份验证的加密,因为它提供了*机密性和真实性。请参阅OpenSSL wiki上的[EVP Authenticated Encryption and Decryption](http://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption)。 – jww

回答

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

0

的问题是,当我试图到加密4096个字节它也增加了我16个字节PADD的,它是失败的我。我不知道为什么要添加填充,因为4096是128的倍数(size aes block)。

正如Zaph所述,PKCS#7填充正在添加中。填充是确定性的,所以16个填充的确切倍数也被填充以确保去除。否则,广义算法如何知道何时(1)纯文本在16字节边界上结束,与(2)纯文本而不是以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);