OpenSSL DecryptFinal错误的最终块长度

时间:2016-06-25 19:16:27

标签: c encryption openssl

我正在使用OpenSSL和C语言来创建加密和解密应用程序。我有一个头文件(我必须按原样使用,无法修改),这是:

#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/rsa.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include <openssl/evp.h>
#include <stdio.h>
#include <stdint.h>

#define CSM_SYM_KEY_MAX_SIZE 1024

typedef uint32_t uint32;
typedef uint16_t uint16;
typedef uint8_t uint8;
typedef uint16 Csm_ConfigIdType;
typedef uint8 Csm_AlignType; 


typedef struct Csm_SymKeyType{
    uint32 length;
    Csm_AlignType data[CSM_SYM_KEY_MAX_SIZE];
} Csm_SymKeyType;

typedef enum Std_ReturnType {
    E_OK,               /*  Request successful  */                   
    E_NOT_OK,           /*  Request failed  */                                  
    CSM_E_BUSY,         /*  Request failed, service is still busy   */          
    CSM_E_SMALL_BUFFER  /*  The provider buffer is too small to store the result    */
} Std_ReturnType;

/* Encryption functions */
Std_ReturnType Csm_SymBlockEncryptStart(Csm_ConfigIdType cfgId,    Csm_SymKeyType *keyPtr);
Std_ReturnType Csm_SymBlockEncryptUpdate(Csm_ConfigIdType cfgId, const uint8 *plaintextPtr, uint32 plainTextLength, 
                                        uint8 *cipherTextPtr, uint32 *plainTextLengthPtr);
Std_ReturnType Csm_SymBlockEncryptFinish(Csm_ConfigIdType cfgId);

/* Decryption functions */
Std_ReturnType Csm_SymBlockDecryptStart(Csm_ConfigIdType cfgId, Csm_SymKeyType *keyPtr);
Std_ReturnType Csm_SymBlockDecryptUpdate(Csm_ConfigIdType cfgId, const uint8 *cipherTextPtr, uint32 cipherTextLength, 
                                        uint8 *plainTextPtr, uint32 *cipherTextLengthPtr);
Std_ReturnType Csm_SymBlockDecryptFinish(Csm_ConfigIdType cfgId);

我写的代码是:

#include "CSM_library.h"

EVP_CIPHER_CTX *ctx;
uint32 ciphertext_len;
uint32 plaintext_len;
uint32 ct_len;
uint32 pt_len;
uint8 *ciphertext;
uint8 *plaintext;
uint8 *iv;

void OPENSSL_config();

Csm_SymKeyType *keyPtr;

void handleErrors(void){

    ERR_print_errors_fp(stderr);
    abort();
}

void ctx_init(){

    ERR_load_crypto_strings();
    OpenSSL_add_all_algorithms();
    OPENSSL_config(NULL);
    ctx = EVP_CIPHER_CTX_new();
    if (ctx == NULL)
        handleErrors();

    return;

}

void ctx_finish(){

    EVP_CIPHER_CTX_free(ctx);
    EVP_cleanup();
    return;
}

Std_ReturnType Csm_SymBlockEncryptStart(Csm_ConfigIdType cfgId, Csm_SymKeyType *keyPtr){

    uint32 ret;
    ct_len = 0;
    ciphertext_len = 0;
    ctx_init();
    ret = EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, keyPtr->data, iv);
    if (ret != 1)
        handleErrors();
    return E_OK;
}

Std_ReturnType Csm_SymBlockEncryptUpdate(Csm_ConfigIdType cfgId, const uint8 *plainTextPtr, uint32 plainTextLength, 
                                        uint8 *cipherTextPtr, uint32 *plainTextLengthPtr){

    uint32 ret;
    ret = EVP_EncryptUpdate(ctx, cipherTextPtr, &ct_len, plainTextPtr, plainTextLength);
    if (ret != 1)
        handleErrors();
    ciphertext_len = ct_len;
    ciphertext = cipherTextPtr;
    return E_OK;
}

Std_ReturnType Csm_SymBlockEncryptFinish(Csm_ConfigIdType cfgId){

    uint32 ret;
    ret = EVP_EncryptFinal_ex(ctx, ciphertext + ct_len, &ct_len);
    if (ret != 1)
        handleErrors();
    ciphertext_len += ct_len;
    ctx_finish();
    return E_OK;
}

Std_ReturnType Csm_SymBlockDecryptStart(Csm_ConfigIdType cfgId, Csm_SymKeyType *keyPtr){

    uint32 ret;
    pt_len = 0;
    plaintext_len = 0;
    ctx_init();
    ret = EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, keyPtr->data, iv);
    if (ret != 1)
        handleErrors();
    return E_OK;
}

Std_ReturnType Csm_SymBlockDecryptUpdate(Csm_ConfigIdType cfgId, const uint8 *cipherTextPtr, uint32 cipherTextLength, 
                                        uint8 *plainTextPtr, uint32 *cipherTextLengthPtr){

    uint32 ret;
    ret = EVP_DecryptUpdate(ctx, plainTextPtr, &pt_len, cipherTextPtr, cipherTextLength);
    if (ret != 1)
        handleErrors(); 
    plaintext_len = pt_len;
    plaintext = plainTextPtr;
    return E_OK;
}

Std_ReturnType Csm_SymBlockDecryptFinish(Csm_ConfigIdType cfgId){

    uint32 ret;
    ret = EVP_DecryptFinal_ex(ctx, plaintext + pt_len, &pt_len);
    if (ret != 1)
        handleErrors(); 
    plaintext_len += pt_len;
    ctx_finish();
    return E_OK;
}

int main(){

    Csm_ConfigIdType cfgId;
    uint32 key_size;
    uint32 iv_size;
    uint32 cipherTextLength;
    uint32 plainTextLength;
    uint32 *plainTextLengthPtr;
    uint32 *cipherTextLengthPtr;
    const uint8 *plainTextPtr = "In the midway of this our mortal life, I found me in a gloomy wood";
    const uint8 *cipherTextPtr2;


    key_size = EVP_MAX_KEY_LENGTH;    //64
    iv_size = 4;

    plainTextLength = strlen(plainTextPtr);
    plainTextLengthPtr = &plainTextLength;

    uint8 cipherTextPtr[128];
    uint8 plainTextPtr2[128]; 

    uint8 key[key_size];
    iv = malloc(iv_size);


    /*  create key and inizialization vector  */
    RAND_bytes(key, key_size);
    RAND_bytes(iv, iv_size);

    keyPtr = malloc(sizeof(Csm_SymKeyType));
    if (keyPtr == NULL){
        printf("malloc() fails");
        exit(1);
    }

    keyPtr->length = key_size;
    memcpy(keyPtr->data, key, key_size);

    /*  encryption  */
    Csm_SymBlockEncryptStart(cfgId, keyPtr);
    Csm_SymBlockEncryptUpdate(cfgId, plainTextPtr, plainTextLength, cipherTextPtr, plainTextLengthPtr);
    Csm_SymBlockEncryptFinish(cfgId);

    printf("Ciphertext is:\n");
    BIO_dump_fp(stdout, (const char *)cipherTextPtr, cipherTextLength);

    /*  decryption  */
    Csm_SymBlockDecryptStart(cfgId, keyPtr);
    cipherTextPtr2 = cipherTextPtr;
    cipherTextLength = strlen(cipherTextPtr2);

    cipherTextLengthPtr = &cipherTextLength;
    Csm_SymBlockDecryptUpdate(cfgId, cipherTextPtr2, cipherTextLength, plainTextPtr2, cipherTextLengthPtr);
    Csm_SymBlockDecryptFinish(cfgId);

    plainTextPtr2[strlen(plainTextPtr2)] = '\0';
    printf("Plaintext: %s\nof length %i\n", plainTextPtr2, strlen(plainTextPtr2));

    free(keyPtr);
    return 0;
}    

我知道代码可以写得比它好,但它只是一个试验,我只是让它在这一步工作。 加密很好,解密阶段是可变的,有时它会没有错误地进行,但解密不正确(它在最后增加了一些内容和一些换行符):

Plaintext: This is my plaintext!










                                x-gnu/libcrypto.
of length 48

有时它会在执行期间给我这个错误:

140614667638424:error:0606506D:digital envelope  routines:EVP_DecryptFinal_ex:wrong final block length:evp_enc.c:581:
Aborted (core dumped)

阅读错误消息我认为它与解密的块长度有关,但我一再检查函数EVP_DecryptUpdate()EVP_DecryptFinal(),它们对我来说似乎很好。有人可以帮我解决这个问题吗?提前谢谢。

0 个答案:

没有答案