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

Circom中如何实现任意长度输入的SHA256哈希计算?

报错根因

Circom是静态约束系统,所有数组长度、组件实例化参数、循环边界都必须在编译(约束生成)阶段确定为常量,不能依赖输入信号的运行时值。你编写的代码中用输入信号nBits定义输入数组长度、作为Sha256组件的初始化参数、作为for循环的边界条件,全部违反这一核心规则,因此触发三类编译错误。

可行实现方案

不存在支持真正无限长度输入的Circom电路——电路的约束总数在编译期就是固定值,不可能随输入动态变化。结合你实际业务场景原像长度在100-700字节的范围,采用「固定最大长度+长度约束+标准填充」的行业通用方案即可实现需求,具体逻辑如下:

  • 预设电路支持的最大原像长度为场景上限700字节(即5600比特),所有输入数组、SHA256组件都按这个固定长度在编译期实例化,不依赖任何输入信号作为长度参数。
  • 新增公开输入nBytes表示原像的实际字节长度,添加约束保证nBytes取值在100-700的合法区间内。
  • 原像输入数组固定长度设为5600比特,长度不足700字节的原像,在生成证明时将超出实际长度的数组位置全部填0;电路内添加约束,强制所有索引大于等于nBytes*8的原像位必须为0,防止证明者篡改填充位伪造哈希。
  • 按照SHA256标准规范实现电路内填充逻辑:在原像的实际结束位填1,后续填充0直到满足块长度要求,最后补上64比特的原像总长度(以比特为单位)的大端编码,得到完整的分块输入。
  • 按最大长度对应的SHA256分块数实例化固定的SHA256组件,传入填充完成的输入计算哈希结果。

简化实现示例如下:

pragma circom 2.1.6;
include "circomlib/sha256.circom";
include "circomlib/bitify.circom";
include "circomlib/comparators.circom";

template VariableLengthSha256() {
    // 公开输入:原像实际字节长度
    signal input nBytes;
    // 固定最大长度输入数组:700字节=5600比特
    signal input preimage[5600];
    signal output hash[256];

    // 约束nBytes在100-700的合法区间
    component geCheck = LessThan(10);
    geCheck.in[0] <== nBytes;
    geCheck.in[1] <== 100;
    geCheck.out === 0;
    component leCheck = LessThan(10);
    leCheck.in[0] <== nBytes;
    leCheck.in[1] <== 701;
    leCheck.out === 1;

    signal nBits;
    nBits <== nBytes * 8;
    component nBitsBits = Num2Bits(13); // 5600对应13位二进制
    nBitsBits.in <== nBits;

    var i;
    signal bitIsValid[5600];
    // 约束超出实际长度的preimage位全为0
    for (i = 0; i < 5600; i++) {
        // 生成位选择信号:i < nBits时为1,否则为0
        if (i < 800) { // 最小长度100字节,前800位始终有效
            bitIsValid[i] <== 1;
        } else {
            // 此处通过二进制位比较实现i < nBits的约束,省略具体实现细节
            // 核心约束:无效位必须为0
            preimage[i] * (1 - bitIsValid[i]) === 0;
        }
    }

    // 按SHA256标准填充,最终得到12个块共6144比特的输入(700字节对应12个512比特块)
    signal padded[6144];
    // 省略填充逻辑:按规范填1、填0、填64位长度字段

    // 实例化固定块数的SHA256组件
    component sha256 = Sha256(12);
    for (i=0; i<6144; i++) {
        sha256.in[i] <== padded[i];
    }
    for (i=0; i<256; i++) {
        hash[i] <== sha256.out[i];
    }
}

注意事项

  • 不要尝试动态实例化组件或者动态长度数组,所有ZK约束系统都是静态的,必须预设业务场景的最大输入长度,不存在真正“任意长度”的电路实现。
  • 700字节对应的SHA256电路约束数在合理范围,不会造成证明性能问题。
  • 填充逻辑必须严格对齐标准SHA256规范,否则链下计算的哈希和电路内结果无法匹配,生产环境建议直接使用经过审计的成熟封装模板,不要从零实现压缩、填充逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 15:54:22