You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

IDEA/CFB模式解密首块数据损坏问题求助(OpenSSL 1.1.0g)

Fixing Corrupted First Block in IDEA/CFB Decryption with OpenSSL 1.1.0g

Let's break down the issues in your code that are causing the first 8-byte block to be corrupted, and fix them step by step:

Key Issues Identified

1. Incorrect IV Array Indexing

Your code reads the IV from positions 16-24 of the key buffer, but assigns it to iv[i] directly—this is out of bounds for the 8-byte iv array. The correct indices for iv should start at 0, not 16. This leads to a garbled IV, which directly breaks the first block decryption in CFB mode (since CFB uses the IV to generate the first keystream block).

2. Mismatched CFB Mode in Initialization

You printed the parameters for EVP_idea_cfb64() but initialized the cipher with EVP_idea_cfb()—these are different modes (EVP_idea_cfb() is CFB8, while EVP_idea_cfb64() is 64-bit CFB, matching IDEA's 8-byte block size). Using the wrong mode causes keystream generation to misalign, corrupting the first block.

3. Improper Decryption Output Buffer Management

  • You didn't accumulate the output length from EVP_CipherUpdate, so EVP_DecryptFinal_ex writes to the start of the plain buffer, overwriting part of the decrypted data.
  • The final block needs to be written to the end of the already decrypted data, not the start.

4. Unsafe File Reading

Your read_file function uses a fixed BUFFER_SIZE for reading, which might not match the actual file size. You should read exactly the file size you retrieved with lseek.

Corrected Code

#include <fcntl.h> /* O_RDONLY */
#include <stdio.h> /* printf */
#include <string.h> /* memcpy */
#include <unistd.h> /* read */
#include <openssl/idea.h>
#include <openssl/evp.h>
#include <openssl/ripemd.h>

#define BUFFER_SIZE 861

unsigned char key[16];
unsigned char iv[8];

int read_file(char *file, unsigned char *buffer);

int main(void) {
    unsigned char buffer[BUFFER_SIZE];
    unsigned char cipher_buffer[BUFFER_SIZE];
    unsigned char plain[BUFFER_SIZE] = {0}; // Initialize to zero to avoid garbage output
    EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
    char *cipher = "./cipher.bin";
    char *key1 = "./key.bin";

    // Read key and IV
    int key_file_size = read_file(key1, buffer);
    if (key_file_size <= 0) {
        fprintf(stderr, "Failed to read key file\n");
        EVP_CIPHER_CTX_free(ctx);
        return 1;
    }
    printf("\nKeylength: %d\n", EVP_CIPHER_key_length(EVP_idea_cfb64()));
    printf("IV Length: %d\n", EVP_CIPHER_iv_length(EVP_idea_cfb64()));

    printf("\nKEY:");
    for(int i = 0; i < 16; i++){
        key[i] = buffer[i];
        printf("%d ", buffer[i]);
    }

    printf("\nIV : ");
    for(int i = 16; i < 24; i++){
        iv[i - 16] = buffer[i]; // Fix: correct IV array indexing
        printf("%d ", iv[i - 16]);
    }

    // Read ciphertext
    int cipherLen = read_file(cipher, cipher_buffer);
    if (cipherLen <= 0) {
        fprintf(stderr, "Failed to read cipher file\n");
        EVP_CIPHER_CTX_free(ctx);
        return 1;
    }

    int outlen = 0;
    int temp_len = 0;

    // Initialize cipher context with correct CFB64 mode
    if (!EVP_CipherInit_ex(ctx, EVP_idea_cfb64(), NULL, key, iv, 0)) {
        fprintf(stderr, "Cipher initialization failed\n");
        EVP_CIPHER_CTX_free(ctx);
        return 1;
    }

    // Decrypt main data block
    if (!EVP_CipherUpdate(ctx, plain, &temp_len, cipher_buffer, cipherLen)) {
        fprintf(stderr, "Cipher update failed\n");
        EVP_CIPHER_CTX_free(ctx);
        return 1;
    }
    outlen += temp_len;

    // Decrypt final block (handles padding for CFB if needed)
    if (!EVP_DecryptFinal_ex(ctx, plain + outlen, &temp_len)) {
        fprintf(stderr, "Final decrypt failed\n");
        EVP_CIPHER_CTX_free(ctx);
        return 1;
    }
    outlen += temp_len;

    // Print the full decrypted plaintext
    printf("\nDecrypted plaintext:\n%.*s\n", outlen, plain);

    EVP_CIPHER_CTX_free(ctx);
    return 0;
}

int read_file(char *file, unsigned char *buffer){
    int fp = open(file, O_RDONLY);
    if (fp == -1) {
        perror("File not found");
        return -1;
    }

    int f_size = lseek(fp, 0, SEEK_END);
    if (f_size == -1) {
        perror("Failed to get file size");
        close(fp);
        return -1;
    }
    lseek(fp, 0, SEEK_SET);

    printf("File size for %s: %d\n", file, f_size);
    ssize_t bytes_read = read(fp, buffer, f_size); // Read exactly the file size
    if (bytes_read != f_size) {
        perror("Failed to read full file");
        close(fp);
        return -1;
    }

    close(fp);
    return f_size;
}

Additional Notes

  • Always check the return values of OpenSSL functions—they return 1 on success, 0 on failure, which helps catch initialization or decryption errors early.
  • We added close(fp) in read_file to avoid file descriptor leaks.
  • The plain buffer is initialized to zero to prevent printing uninitialized garbage after the decrypted data.

内容的提问来源于stack exchange,提问作者Twin322

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:04:54