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

Django集成CCAvenue支付网关时遇AES密钥大小无效错误

解决Django集成CCAvenue支付网关时的AES密钥长度错误问题

问题场景

在Django 4.2.1项目中集成CCAvenue支付网关,使用ccav_app/ccav_utils.py中的加解密函数处理数据与密钥,POST请求访问/cc/路径时触发ValueError: Invalid key size (352) for AES错误。

问题根源

  1. 密钥长度异常:derive_key函数中,PBKDF2HMAC已生成符合AES-256要求的32字节(256位)密钥,但后续执行base64.urlsafe_b64encode将其编码为44字节(352位)的字符串,而AES仅支持128/192/256位密钥,导致密钥长度不符合要求。
  2. salt不一致:derive_key每次调用都会生成随机salt,导致加密和解密时派生的密钥完全不同,即使去掉base64编码,也会出现解密失败的问题。
  3. padding导入冲突:代码中同时导入了非对称加密的padding和对称加密的sym_padding,但pad/unpad函数错误使用了非对称加密的padding,可能引发潜在问题。

修复方案

修改核心函数逻辑

  1. 修正derive_key:去掉base64编码,直接返回派生的字节密钥;同时返回salt,确保加密解密使用同一salt。
  2. 调整encrypt函数:将salt、iv、加密数据拼接后再base64编码,让解密端能获取到salt。
  3. 调整decrypt函数:先从加密数据中提取salt,再用该salt派生密钥,确保密钥一致。
  4. 修正padding引用:pad/unpad函数使用sym_padding而非非对称加密的padding。

修改后的完整代码

# ccav_app/ccav_utils.py

from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import padding as sym_padding
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
import base64
import os

def pad(data):
    padder = sym_padding.PKCS7(128).padder()
    padded_data = padder.update(data) + padder.finalize()
    return padded_data

def unpad(data):
    unpadder = sym_padding.PKCS7(128).unpadder()
    unpadded_data = unpadder.update(data) + unpadder.finalize()
    return unpadded_data

def derive_key(secret_key, salt=None):
    if salt is None:
        salt = os.urandom(16)  # 生成随机salt(16字节)
    kdf = PBKDF2HMAC(
        algorithm=hashes.SHA256(),
        iterations=100000,
        salt=salt,
        length=32,  # 生成32字节(256位)密钥,符合AES-256要求
        backend=default_backend()
    )
    key = kdf.derive(secret_key.encode())
    return key, salt


def encrypt(plain_text, secret_key):
    key, salt = derive_key(secret_key)
    iv = os.urandom(16)
    cipher = Cipher(algorithms.AES(key), modes.CFB(iv), backend=default_backend())
    encryptor = cipher.encryptor()
    # 先对明文做填充
    padded_plain = pad(plain_text.encode())
    encrypted_text = encryptor.update(padded_plain) + encryptor.finalize()
    # 拼接salt + iv + 加密数据,再base64编码
    return base64.b64encode(salt + iv + encrypted_text).decode()

def decrypt(cipher_text, secret_key):
    data = base64.b64decode(cipher_text.encode())
    # 提取前16字节的salt
    salt = data[:16]
    # 提取接下来16字节的iv
    iv = data[16:32]
    # 剩余部分是加密数据
    encrypted_data = data[32:]
    # 使用提取的salt派生密钥
    key, _ = derive_key(secret_key, salt=salt)
    cipher = Cipher(algorithms.AES(key), modes.CFB(iv), backend=default_backend())
    decryptor = cipher.decryptor()
    decrypted_padded = decryptor.update(encrypted_data) + decryptor.finalize()
    # 去掉填充后解码为字符串
    return unpad(decrypted_padded).decode()

额外说明

  • 确保CCAvenue网关的密钥配置与代码中使用的secret_key一致,大小写和特殊字符完全匹配。
  • 测试时可先通过本地调用encrypt和decrypt函数验证加解密逻辑是否正常,再集成到Django的视图中。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 09:42:48