mimc.circom和mimcsponge.circom学习

参考的文章:https://byt3bit.github.io/primesym/mimc/ 

上述文章的作者是MiMC: Efficient Encryption and Cryptographic Hashing with Minimal Multiplicative Complexity的作者之一。

mimc是Minimal Multiplicative Complexity的缩写。

mimc.circom

mimc.circom有两个templates: MiMC7(nrounds)和MultiMiMC7(nInputs, nRounds)。一般调用的是MultiMiMC7模版。

下面三张图是MiMC的主要结构

在MiMC(nrounds) template中会将上述的函数F_i(x)的3次方改成了7次方并且直接固定c_i。所有的运算都在F_p或者F_{2^n}上。我们具体看一下MiMc代码
 

template MiMC7(nrounds) {
    signal input x_in;
    signal input k;
    signal output out;

    var c[91] = [
        0,  //最开始ci并没有参与运算,因此为0
   20888961410941983456478427210666206549300505294776164667214940546594746570981,
      15265126113435022738560151911929040668591755459209400716467504685752745317193,
        ...//这里省略余下的数组元素。
        ];
   var t;
    signal t2[nrounds];
    signal t4[nrounds];
    signal t6[nrounds];
    signal t7[nrounds-1];

    for (var i=0; i<nrounds; i++) {
        t = (i==0) ? k+x_in : k + t7[i-1] + c[i]; 
        //当i==0,则图中最开始的部分
        t2[i] <== t*t;
        t4[i] <== t2[i]*t2[i];
        t6[i] <== t4[i]*t2[i];
        if (i<nrounds-1) {                 
            t7[i] <== t6[i]*t;
        } else {
            out <== t6[i]*t + k; //对应图中最后一部分需要 +k
        }
    }
}

接下来具体看一下MultiMiMC7(nInputs,nRounds)的代码。

template MultiMiMC7(nInputs, nRounds) {
    //显然输入的0<=nRounds<=91,因为调用的MiMC7中的c数组大小最多91
    signal input in[nInputs]; //n个输入
    signal input k;           //给定一个初始的值k
    signal output out;        
    signal r[nInputs +1];
    component mims[nInputs];
    r[0] <== k;                       
    for (var i=0; i<nInputs; i++) {
        mims[i] = MiMC7(nRounds); //主要调用上述的MiMC7 模版
        mims[i].x_in <== in[i];
        mims[i].k <== r[i];          //每次输入到MiMC7中的k值是 r[i]
        r[i+1] <== r[i] + in[i] + mims[i].out;
       //下一次输入到MiMC7中的k值由本次的k值,输入值以及MiMC7本次输出值相加而成
    }
    out <== r[nInputs];
}

mimcsponge.circom

mimcsponge.circom电路文件中有两个templates: MiMCFeistel(nrounds)MiMCSponge(nInputs, nRounds, nOutputs)

MiMCFeistel(nrounds)。这个模版主要实现的是一个等式(x_{i+1},y_{i+1}) = (y_i,x_i+(y_i+k+c_i)^5)

上述等式体现出来的结构就是Feistel轮转结构,将其中的F 替换成(y_i+k+c_i)^5即可。现在我们看一下代码

template MiMCFeistel(nrounds) {
    signal input xL_in;
    signal input xR_in;
    signal input k;
    signal output xL_out;
    signal output xR_out;

    var c_partial[218] = [
      7120861356467848435263064379192047478074060781135320967663101236819528304084,
      //省略剩下217个数组元素
    ];
    var t;
    signal t2[nrounds];
    signal t4[nrounds];
    signal xL[nrounds-1];
    signal xR[nrounds-1];
    var c;
    for (var i=0; i<nrounds; i++) {
        if ((i == 0) || (i == nrounds - 1)) {
          c = 0; // 也就是开始和结束时不需要加c
        } else {
          c = c_partial[i - 1]; 
        }
        t = (i==0) ? k+xL_in : k + xL[i-1] + c; 
        t2[i] <== t*t;
        t4[i] <== t2[i]*t2[i];
        if (i<nrounds-1) {
          var aux = (i==0) ? xR_in : xR[i-1] ; 
          xL[i] <== aux + t4[i]*t;  //本轮的左边xL[i] 会等于上一轮的右边xR[i-1] 加上函数(k + xL[i-1] + c)^5
          xR[i] <== (i==0) ? xL_in : xL[i-1];//本轮的右边xR[i] 会等于上一轮的左边
        } else {
          xR_out <== xR[i-1] + t4[i]*t; //最后一轮不需要
          xL_out <== xL[i-1];
        }
    }
}

MiMCSponge(nInputs, nRounds, nOutputs)

主要的结构为Sponge结构。如图所示:

template MiMCSponge(nInputs, nRounds, nOutputs) {
  signal input ins[nInputs]; //相当于图中的P0,P1,...P_{nInputs-1}
  signal input k;
  signal output outs[nOutputs]; //相当于图中的Z0,Z1,...,Z_{nOutputs-1}
  var i;
  // S = R||C
  component S[nInputs + nOutputs - 1]; 
   // 从0到nInputs-1 是输入;  相当于
   // nInputs 到 nInputs + nOutputs - 1是输出
  for (i = 0; i < nInputs; i++) {
    S[i] = MiMCFeistel(nRounds);
    S[i].k <== k;   //初始值
    if (i == 0) {
      S[i].xL_in <== ins[0]; 
      S[i].xR_in <== 0;
    } else {
      S[i].xL_in <== S[i-1].xL_out + ins[i]; //本轮左边等于函数f输出的左边 + P_i
      S[i].xR_in <== S[i-1].xR_out;   //本轮右边等于 函数f输出的右边
    }
  }

  outs[0] <== S[nInputs - 1].xL_out;
  for (i = 0; i < nOutputs - 1; i++) {
    S[nInputs + i] = MiMCFeistel(nRounds);
    S[nInputs + i].k <== k;
    S[nInputs + i].xL_in <== S[nInputs + i - 1].xL_out;
    S[nInputs + i].xR_in <== S[nInputs + i - 1].xR_out;
    outs[i + 1] <== S[nInputs + i].xL_out;
  }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值