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

AES-256 CBC模式C语言实现的PKCS#7填充问题排查

AES-256 CBC加密C版本与Python/C#结果不一致的问题解决

现有Python和C#实现的AES-256 CBC模式加密程序,加密输出均为9192D9DACF7E02D06F00DB82DFED3E3764C159683BE158F76D95114288F512EA。但使用Tiny AES库编写的C版本仅前32位输出正确,后半段为无效数据,经排查是PKCS#7填充未正确实现导致的,以下是问题分析及解决方案。

原始Python代码

import os
from cryptography.hazmat.primitives.ciphers import (algorithms, modes, Cipher)
from cryptography.hazmat.primitives.padding import PKCS7

text = "6bcdax94cvrdnhvo"
key = "7copiqupo7cpaq7c9u7qab84rpc16gvk"

encodedText = text.encode()
encodedKey = key.encode()

iv = encodedKey[:16]

cipher = Cipher(algorithms.AES(encodedKey), modes.CBC(iv))
encryptor = cipher.encryptor()

padder = PKCS7(128).padder()
pad = padder.update(encodedText) + padder.finalize()
print(encryptor.update(pad))

原始C#代码

using System.Text;
using System.Security.Cryptography;

string text = "6bcdax94cvrdnhvo";
string key = "7copiqupo7cpaq7c9u7qab84rpc16gvk";

byte[] byteKey= Encoding.ASCII.GetBytes(key);

Aes aesAlg = Aes.Create();
aesAlg.Mode = CipherMode.CBC;
aesAlg.Key = byteKey;
aesAlg.IV = byteKey[0..16];

ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
byte[] encrypted = encryptor.TransformFinalBlock(Encoding.ASCII.GetBytes(text), 0, Encoding.ASCII.GetBytes(text).Length);
encryptor.Dispose();

string plainText = BitConverter.ToString(encrypted);
plainText = plainText.Replace("-", "");

Console.WriteLine($@"{plainText}");

原始问题C代码

#include <stdint.h>
#include "aes.h"

int main()
{
    uint8_t text[16] = "6bcdax94cvrdnhvo";
    uint8_t key[32] = "7copiqupo7cpaq7c9u7qab84rpc16gvk";
    uint8_t iv[16];

    int i;
    for (i = 0; i < 16; i++) {
        iv[i] = key[i];
    }

    struct AES_ctx ctx;

    AES_init_ctx_iv(&ctx, key, iv);
    AES_CBC_encrypt_buffer(&ctx, text, 16);

    for (i = 0; i < 16; i++) {
        printf("%.2x", text[i]);
    }

    return 0;
}

问题分析

  • 填充缺失:Python和C#的代码都自动处理了PKCS#7填充(Python显式调用PKCS7填充器,C#的TransformFinalBlock默认添加PKCS#7填充),而原始C代码完全没有实现填充逻辑。
  • 数据长度规则:待加密的明文"6bcdax94cvrdnhvo"刚好是16字节(AES单块大小),按照PKCS#7规则,此时必须填充一个完整的块(16个0x10字节),否则加密后的结果会少一个块,仅前半段匹配预期输出。

解决方案

在C代码中手动实现PKCS#7填充逻辑,将明文缓冲区扩展为32字节(两个AES块),填充后再执行加密操作。

修正后的C代码

#include <stdint.h>
#include <string.h>
#include "aes.h"

// PKCS#7填充实现
void pkcs7_pad(uint8_t *data, size_t data_len, size_t block_size) {
    uint8_t pad_len = block_size - (data_len % block_size);
    memset(data + data_len, pad_len, pad_len);
}

int main()
{
    // 明文刚好16字节,需填充16字节,缓冲区设为32字节
    uint8_t text[32] = "6bcdax94cvrdnhvo";
    uint8_t key[32] = "7copiqupo7cpaq7c9u7qab84rpc16gvk";
    uint8_t iv[16];
    size_t text_len = strlen((char*)text);
    const size_t block_size = 16;

    int i;
    for (i = 0; i < 16; i++) {
        iv[i] = key[i];
    }

    // 执行PKCS#7填充
    pkcs7_pad(text, text_len, block_size);

    struct AES_ctx ctx;

    AES_init_ctx_iv(&ctx, key, iv);
    // 加密32字节数据(两个完整块)
    AES_CBC_encrypt_buffer(&ctx, text, 32);

    for (i = 0; i < 32; i++) {
        printf("%.2x", text[i]);
    }
    printf("\n");

    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 01:28:10