RISC-V MCU中文社区

【分享】 第三代安全算法SHA3 Keccack核心分享

发表于 GD32VF103 MCU 2021-07-25 19:49:24
0
404
3

大家好,我们是这是一件好事队,今天为大家分享第三代安全算法SHA3(Keccack核心)的硬件实现代码。

NIST2012年评选出了最终的算法并确定了新的哈希函数标准。Keccak算法由于其较强的安全性和优秀的软硬件实现性能,最终成为最新一代的哈希函数标准。20158NIST发布了最终的 SHA-3 算法标准《FIPS PUB 202—SHA-3 Standard: Permutation-Based Hash and Extendable-Output Functions》。 

SHA-3算法同样是一种迭代哈希函数,但是采用了更先进的海绵结构,海绵结构是由Bertoni等人提出的一种用于将输入数据流压缩为任意长度输出的函数架构, 可以分为吸收和挤压两个阶段(如 3‑3)。图中pad表示输入消息填充规则,f表示用于处理固定长度消息的底层迭代函数,r表示消息分组长度,c表示冗余容量,其中b = r + c表示比特率,也是整个运算过程中处理的中间状态的位宽。

SHA-3算法中,采用的填充规则被称为“pad10*1”,其中的星号表示需要填充 的“0”可以被省略或多次重复。具体规则是,在消息后添加单比特的“1”,中间添加多比特的“0”,最后再添加单比特的“1”,使填充后的消息长度是消息分组长度的整数倍。填充后的消息按照分组长度拆分为P1P2...Pn多个消息块,在算法吸收阶段被分块吸收。


算法吸收阶段,是使用迭代函数f对中间状态进行置换的同时,将分组后的消息分多次进行吸收。在第一次吸收前,中间状态的初始值为全零,将其低r比特与第一块消息P1按位异或后,拼接上原状态的高c比特作为迭代函数的输入;第二次吸收时,将上一阶段输出中间状态的低r比特与第二块消息P2按位异或,之后拼接上一阶段输出中间状态的高c比特,作为下一次迭代函数的输入;以此类推,完成所有消息块的吸收。

在算法挤压阶段,根据最后所需消息摘要的长度确定挤压阶段需要调用迭代函数 的次数。由于SHA-3算法对消息摘要长度的要求都小于消息分组长度c,则SHA-3算法在挤压阶段不需要调用迭代函数,直接截取最后一次吸收后输出中间状态的低位, 就能得到最终的消息摘要。

根据SHA-3算法标准,中间状态长度固定为1600比特,并且为了方便定义迭代函数中的具体运算,中间状态需按照一个5x5x64的三维矩阵如 进行组织。



    每次调用迭代函数时,输入及输出状态到三维矩阵的映射关系,应该遵循以下公式: A [x,y,z]=S[64(x + 5y) + z] 根据SHA-3算法标准,每调用一次迭代函数需要进行24轮迭代运算,每一轮迭代运算又需要完成规定的五步迭代。五步迭代作为整个循环迭代过程中的核心运算,具体定义如下:


软件实现代码:


static const uint64_t KeccakF_RoundConstants[NROUNDS] = 
{
    (uint64_t)0x0000000000000001ULL,
    (uint64_t)0x0000000000008082ULL,
    (uint64_t)0x800000000000808aULL,
    (uint64_t)0x8000000080008000ULL,
    (uint64_t)0x000000000000808bULL,
    (uint64_t)0x0000000080000001ULL,
    (uint64_t)0x8000000080008081ULL,
    (uint64_t)0x8000000000008009ULL,
    (uint64_t)0x000000000000008aULL,
    (uint64_t)0x0000000000000088ULL,
    (uint64_t)0x0000000080008009ULL,
    (uint64_t)0x000000008000000aULL,
    (uint64_t)0x000000008000808bULL,
    (uint64_t)0x800000000000008bULL,
    (uint64_t)0x8000000000008089ULL,
    (uint64_t)0x8000000000008003ULL,
    (uint64_t)0x8000000000008002ULL,
    (uint64_t)0x8000000000000080ULL,
    (uint64_t)0x000000000000800aULL,
    (uint64_t)0x800000008000000aULL,
    (uint64_t)0x8000000080008081ULL,
    (uint64_t)0x8000000000008080ULL,
    (uint64_t)0x0000000080000001ULL,
    (uint64_t)0x8000000080008008ULL
};

/*************************************************
* Name:        KeccakF1600_StatePermute
* 
* Description: The Keccak F1600 Permutation
*
* Arguments:   - uint64_t * state: pointer to in/output Keccak state
**************************************************/
void KeccakF1600_StatePermute(uint64_t * state)
{
  int round;

        uint64_t Aba, Abe, Abi, Abo, Abu;
        uint64_t Aga, Age, Agi, Ago, Agu;
        uint64_t Aka, Ake, Aki, Ako, Aku;
        uint64_t Ama, Ame, Ami, Amo, Amu;
        uint64_t Asa, Ase, Asi, Aso, Asu;
        uint64_t BCa, BCe, BCi, BCo, BCu;
        uint64_t Da, De, Di, Do, Du;
        uint64_t Eba, Ebe, Ebi, Ebo, Ebu;
        uint64_t Ega, Ege, Egi, Ego, Egu;
        uint64_t Eka, Eke, Eki, Eko, Eku;
        uint64_t Ema, Eme, Emi, Emo, Emu;
        uint64_t Esa, Ese, Esi, Eso, Esu;
		
		//printf("\n����\n"); 
		for(int i=0;i<25;i++)
		{
			//printf("%llx\n",state[i]);
		}
        //copyFromState(A, state)
        Aba = state[ 0];
        Abe = state[ 1];
        Abi = state[ 2];
        Abo = state[ 3];
        Abu = state[ 4];
        Aga = state[ 5];
        Age = state[ 6];
        Agi = state[ 7];
        Ago = state[ 8];
        Agu = state[ 9];
        Aka = state[10];
        Ake = state[11];
        Aki = state[12];
        Ako = state[13];
        Aku = state[14];
        Ama = state[15];
        Ame = state[16];
        Ami = state[17];
        Amo = state[18];
        Amu = state[19];
        Asa = state[20];
        Ase = state[21];
        Asi = state[22];
        Aso = state[23];
        Asu = state[24];

        for( round = 0; round < NROUNDS; round += 2 )
        {
            //    prepareTheta
            BCa = Aba^Aga^Aka^Ama^Asa;
            BCe = Abe^Age^Ake^Ame^Ase;
            BCi = Abi^Agi^Aki^Ami^Asi;
            BCo = Abo^Ago^Ako^Amo^Aso;
            BCu = Abu^Agu^Aku^Amu^Asu;

            //thetaRhoPiChiIotaPrepareTheta(round  , A, E)
            Da = BCu^ROL(BCe, 1);
            De = BCa^ROL(BCi, 1);
            Di = BCe^ROL(BCo, 1);
            Do = BCi^ROL(BCu, 1);
            Du = BCo^ROL(BCa, 1);

            Aba ^= Da;
            BCa = Aba;
            Age ^= De;
            BCe = ROL(Age, 44);
            Aki ^= Di;
            BCi = ROL(Aki, 43);
            Amo ^= Do;
            BCo = ROL(Amo, 21);
            Asu ^= Du;
            BCu = ROL(Asu, 14);
            Eba =   BCa ^((~BCe)&  BCi );
            Eba ^= (uint64_t)KeccakF_RoundConstants[round];
            Ebe =   BCe ^((~BCi)&  BCo );
            Ebi =   BCi ^((~BCo)&  BCu );
            Ebo =   BCo ^((~BCu)&  BCa );
            Ebu =   BCu ^((~BCa)&  BCe );

            Abo ^= Do;
            BCa = ROL(Abo, 28);
            Agu ^= Du;
            BCe = ROL(Agu, 20);
            Aka ^= Da;
            BCi = ROL(Aka,  3);
            Ame ^= De;
            BCo = ROL(Ame, 45);
            Asi ^= Di;
            BCu = ROL(Asi, 61);
            Ega =   BCa ^((~BCe)&  BCi );
            Ege =   BCe ^((~BCi)&  BCo );
            Egi =   BCi ^((~BCo)&  BCu );
            Ego =   BCo ^((~BCu)&  BCa );
            Egu =   BCu ^((~BCa)&  BCe );

            Abe ^= De;
            BCa = ROL(Abe,  1);
            Agi ^= Di;
            BCe = ROL(Agi,  6);
            Ako ^= Do;
            BCi = ROL(Ako, 25);
            Amu ^= Du;
            BCo = ROL(Amu,  8);
            Asa ^= Da;
            BCu = ROL(Asa, 18);
            Eka =   BCa ^((~BCe)&  BCi );
            Eke =   BCe ^((~BCi)&  BCo );
            Eki =   BCi ^((~BCo)&  BCu );
            Eko =   BCo ^((~BCu)&  BCa );
            Eku =   BCu ^((~BCa)&  BCe );

            Abu ^= Du;
            BCa = ROL(Abu, 27);
            Aga ^= Da;
            BCe = ROL(Aga, 36);
            Ake ^= De;
            BCi = ROL(Ake, 10);
            Ami ^= Di;
            BCo = ROL(Ami, 15);
            Aso ^= Do;
            BCu = ROL(Aso, 56);
            Ema =   BCa ^((~BCe)&  BCi );
            Eme =   BCe ^((~BCi)&  BCo );
            Emi =   BCi ^((~BCo)&  BCu );
            Emo =   BCo ^((~BCu)&  BCa );
            Emu =   BCu ^((~BCa)&  BCe );

            Abi ^= Di;
            BCa = ROL(Abi, 62);
            Ago ^= Do;
            BCe = ROL(Ago, 55);
            Aku ^= Du;
            BCi = ROL(Aku, 39);
            Ama ^= Da;
            BCo = ROL(Ama, 41);
            Ase ^= De;
            BCu = ROL(Ase,  2);
            Esa =   BCa ^((~BCe)&  BCi );
            Ese =   BCe ^((~BCi)&  BCo );
            Esi =   BCi ^((~BCo)&  BCu );
            Eso =   BCo ^((~BCu)&  BCa );
            Esu =   BCu ^((~BCa)&  BCe );

            //    prepareTheta
            BCa = Eba^Ega^Eka^Ema^Esa;
            BCe = Ebe^Ege^Eke^Eme^Ese;
            BCi = Ebi^Egi^Eki^Emi^Esi;
            BCo = Ebo^Ego^Eko^Emo^Eso;
            BCu = Ebu^Egu^Eku^Emu^Esu;

            //thetaRhoPiChiIotaPrepareTheta(round+1, E, A)
            Da = BCu^ROL(BCe, 1);
            De = BCa^ROL(BCi, 1);
            Di = BCe^ROL(BCo, 1);
            Do = BCi^ROL(BCu, 1);
            Du = BCo^ROL(BCa, 1);

            Eba ^= Da;
            BCa = Eba;
            Ege ^= De;
            BCe = ROL(Ege, 44);
            Eki ^= Di;
            BCi = ROL(Eki, 43);
            Emo ^= Do;
            BCo = ROL(Emo, 21);
            Esu ^= Du;
            BCu = ROL(Esu, 14);
            Aba =   BCa ^((~BCe)&  BCi );
            Aba ^= (uint64_t)KeccakF_RoundConstants[round+1];
            Abe =   BCe ^((~BCi)&  BCo );
            Abi =   BCi ^((~BCo)&  BCu );
            Abo =   BCo ^((~BCu)&  BCa );
            Abu =   BCu ^((~BCa)&  BCe );

            Ebo ^= Do;
            BCa = ROL(Ebo, 28);
            Egu ^= Du;
            BCe = ROL(Egu, 20);
            Eka ^= Da;
            BCi = ROL(Eka, 3);
            Eme ^= De;
            BCo = ROL(Eme, 45);
            Esi ^= Di;
            BCu = ROL(Esi, 61);
            Aga =   BCa ^((~BCe)&  BCi );
            Age =   BCe ^((~BCi)&  BCo );
            Agi =   BCi ^((~BCo)&  BCu );
            Ago =   BCo ^((~BCu)&  BCa );
            Agu =   BCu ^((~BCa)&  BCe );

            Ebe ^= De;
            BCa = ROL(Ebe, 1);
            Egi ^= Di;
            BCe = ROL(Egi, 6);
            Eko ^= Do;
            BCi = ROL(Eko, 25);
            Emu ^= Du;
            BCo = ROL(Emu, 8);
            Esa ^= Da;
            BCu = ROL(Esa, 18);
            Aka =   BCa ^((~BCe)&  BCi );
            Ake =   BCe ^((~BCi)&  BCo );
            Aki =   BCi ^((~BCo)&  BCu );
            Ako =   BCo ^((~BCu)&  BCa );
            Aku =   BCu ^((~BCa)&  BCe );

            Ebu ^= Du;
            BCa = ROL(Ebu, 27);
            Ega ^= Da;
            BCe = ROL(Ega, 36);
            Eke ^= De;
            BCi = ROL(Eke, 10);
            Emi ^= Di;
            BCo = ROL(Emi, 15);
            Eso ^= Do;
            BCu = ROL(Eso, 56);
            Ama =   BCa ^((~BCe)&  BCi );
            Ame =   BCe ^((~BCi)&  BCo );
            Ami =   BCi ^((~BCo)&  BCu );
            Amo =   BCo ^((~BCu)&  BCa );
            Amu =   BCu ^((~BCa)&  BCe );

            Ebi ^= Di;
            BCa = ROL(Ebi, 62);
            Ego ^= Do;
            BCe = ROL(Ego, 55);
            Eku ^= Du;
            BCi = ROL(Eku, 39);
            Ema ^= Da;
            BCo = ROL(Ema, 41);
            Ese ^= De;
            BCu = ROL(Ese, 2);
            Asa =   BCa ^((~BCe)&  BCi );
            Ase =   BCe ^((~BCi)&  BCo );
            Asi =   BCi ^((~BCo)&  BCu );
            Aso =   BCo ^((~BCu)&  BCa );
            Asu =   BCu ^((~BCa)&  BCe );
        }

        //copyToState(state, A)
        state[ 0] = Aba;
        state[ 1] = Abe;
        state[ 2] = Abi;
        state[ 3] = Abo;
        state[ 4] = Abu;
        state[ 5] = Aga;
        state[ 6] = Age;
        state[ 7] = Agi;
        state[ 8] = Ago;
        state[ 9] = Agu;
        state[10] = Aka;
        state[11] = Ake;
        state[12] = Aki;
        state[13] = Ako;
        state[14] = Aku;
        state[15] = Ama;
        state[16] = Ame;
        state[17] = Ami;
        state[18] = Amo;
        state[19] = Amu;
        state[20] = Asa;
        state[21] = Ase;
        state[22] = Asi;
        state[23] = Aso;
        state[24] = Asu;
	
        #undef    round
}



硬件实现代码:

module KeccakF1600_StatePermute(clk,start,rst,init,Sin,busy,valid,Sout);

parameter b = 1600;

input [0:b-1]Sin;

input clk,start,rst,init;

output busy,valid;

output [0:b-1]Sout;


wire [0:63]Statein[5][5];

logic valid;

logic busy;

logic [4:0] cycle_num;

logic [0:63]product[5][5];

wire co;


 // S->A转化


genvar x,y,z;

generate

    for(x=0;x<5;x++)

    begin

        for(y=0;y<5;y++)

        begin

            for(z=0;z<64;z++)

            begin

                assign Statein[x][y][z] = Sin [64 * (5*y + x) + z] ;

            end

        end

    end

endgenerate


wire [0:63]A[5][5];

assign A=(start&~busy)? Statein:product;


//theta *********************//


    //theta1

wire [0:63]C[5];

generate

    for(x=0;x<5;x++)

    begin

        for(z=0;z<64;z++)

        begin

            assign C[x][z]=A[x][0][z]^A[x][1][z]^A[x][2][z]^A[x][3][z]^A[x][4][z];

        end

    end

endgenerate

    //theta2 可能要改

wire [0:63]D[5];

generate

    for(x=0;x<5;x++)

    begin

        for(z=0;z<64;z++)

        begin

            assign D[x][z]= C[(x+4)%5][z] ^ C[(x+1)%5][(z+1)%64];

        end

    end

endgenerate

    //theta 3

wire [0:63]theta_out [5][5];

generate

    for(x=0;x<5;x++)

    begin

        for(z=0;z<64;z++)

        begin

            for(y=0;y<5;y++)

            begin

                assign theta_out[x][y][z]=A[x][y][z]^D[x][z];

            end

        end

    end

endgenerate

//*********************//

//rou ****************//

wire [0:63]rou_out[5][5];

assign rou_out[0][0]={theta_out[0][0]};

assign rou_out[1][0]={theta_out[1][0][ 1:63],theta_out[1][0][ 0]};

assign rou_out[2][0]={theta_out[2][0][62:63],theta_out[2][0][0:61]};

assign rou_out[3][0]={theta_out[3][0][28:63],theta_out[3][0][0:27]};

assign rou_out[4][0]={theta_out[4][0][27:63],theta_out[4][0][0:26]};

assign rou_out[0][1]={theta_out[0][1][36:63],theta_out[0][1][0:35]};

assign rou_out[1][1]={theta_out[1][1][44:63],theta_out[1][1][0:43]};

assign rou_out[2][1]={theta_out[2][1][ 6:63],theta_out[2][1][0: 5]};

assign rou_out[3][1]={theta_out[3][1][55:63],theta_out[3][1][0:54]};

assign rou_out[4][1]={theta_out[4][1][20:63],theta_out[4][1][0:19]};

assign rou_out[0][2]={theta_out[0][2][ 3:63],theta_out[0][2][0: 2]};

assign rou_out[1][2]={theta_out[1][2][10:63],theta_out[1][2][0: 9]};

assign rou_out[2][2]={theta_out[2][2][43:63],theta_out[2][2][0:42]};

assign rou_out[3][2]={theta_out[3][2][25:63],theta_out[3][2][0:24]};

assign rou_out[4][2]={theta_out[4][2][39:63],theta_out[4][2][0:38]};

assign rou_out[0][3]={theta_out[0][3][41:63],theta_out[0][3][0:40]};

assign rou_out[1][3]={theta_out[1][3][45:63],theta_out[1][3][0:44]};

assign rou_out[2][3]={theta_out[2][3][15:63],theta_out[2][3][0:14]};

assign rou_out[3][3]={theta_out[3][3][21:63],theta_out[3][3][0:20]};

assign rou_out[4][3]={theta_out[4][3][ 8:63],theta_out[4][3][0: 7]};

assign rou_out[0][4]={theta_out[0][4][18:63],theta_out[0][4][0:17]};

assign rou_out[1][4]={theta_out[1][4][ 2:63],theta_out[1][4][0: 1]};

assign rou_out[2][4]={theta_out[2][4][61:63],theta_out[2][4][0:60]};

assign rou_out[3][4]={theta_out[3][4][56:63],theta_out[3][4][0:55]};

assign rou_out[4][4]={theta_out[4][4][14:63],theta_out[4][4][0:13]};

//*********************//

//pai ****************// 可能要改

wire [0:63]pai_out[5][5];

generate

    for(x=0;x<5;x++)

    begin

        for(y=0;y<5;y++)

        begin

           assign pai_out[x][y]=rou_out[(x+3*y)%5][x];

        end

    end

endgenerate

//********************//

//kai ***************// 可能要改

wire [0:63]kai_out[5][5];

generate

    for(x=0;x<5;x++)

    begin

        for(y=0;y<5;y++)

        begin

            for(z=0;z<64;z++)

            begin

                assign kai_out[x][y][z]=pai_out[x][y][z]^(~pai_out[(x+1)%5][y][z] & pai_out[(x+2)%5][y][z]);

            end

        end

    end

endgenerate

//********************//

//lota **************//

wire [0:63]lota_out[5][5];

logic [6:0]RC;

    //轮数

always@(posedge clk)

begin

    if(rst) cycle_num<=0;

    else if(co) cycle_num<=0;

    else if(busy|start) cycle_num<=cycle_num+1;

    else cycle_num<=0;

end

    //busy

always@(posedge clk)

begin

    if(rst) busy<=0;

    else if(start&~busy) busy<=1;

    else if(co) busy<=0;

end

    //valid

assign co = (cycle_num==23);

always @(posedge clk) begin

    if(rst) valid<=0;

    else if(co) valid<=1;

    else valid<=0;

end

    //product

generate

    for(x=0;x<5;x++)

    begin

        for(y=0;y<5;y++)

        begin

            always @(posedge clk)

            begin

                if(rst|(init&~busy)) product[x][y]<=64'h0;

                else if(busy|start) product[x][y]<=lota_out[x][y];

            end

        end

    end

endgenerate

    //RC

always @(*)

begin

    case (cycle_num)

    5'D0:RC=7'H01;

    5'D1:RC=7'H1A;

    5'D2:RC=7'H5E;

    5'D3:RC=7'H70;

    5'D4:RC=7'H1F;

    5'D5:RC=7'H21;

    5'D6:RC=7'H79;

    5'D7:RC=7'H55;

    5'D8:RC=7'H0E;

    5'D9:RC=7'H0C;

    5'D10:RC=7'H35;

    5'D11:RC=7'H26;

    5'D12:RC=7'H3F;

    5'D13:RC=7'H4F;

    5'D14:RC=7'H5D;

    5'D15:RC=7'H53;

    5'D16:RC=7'H52;

    5'D17:RC=7'H48;

    5'D18:RC=7'H16;

    5'D19:RC=7'H66;

    5'D20:RC=7'H79;

    5'D21:RC=7'H58;

    5'D22:RC=7'H21;

    5'D23:RC=7'H74;

    default RC=7'H00;

endcase

end

generate

    for(x=0;x<5;x++)

    begin

        for(y=1;y<5;y++)

        begin

            assign lota_out[x][y]=kai_out[x][y];

        end

    end

endgenerate

assign lota_out[1][0]=kai_out[1][0];

assign lota_out[2][0]=kai_out[2][0];

assign lota_out[3][0]=kai_out[3][0];

assign lota_out[4][0]=kai_out[4][0];

assign lota_out[0][0]={kai_out[0][0][ 0]^RC[6],kai_out[0][0][ 1:31],

                       kai_out[0][0][32]^RC[5],kai_out[0][0][33:47],

                       kai_out[0][0][48]^RC[4],kai_out[0][0][49:55],

                       kai_out[0][0][56]^RC[3],kai_out[0][0][57:59],

                       kai_out[0][0][60]^RC[2],kai_out[0][0][ 61],

                       kai_out[0][0][62]^RC[1],

                       kai_out[0][0][63]^RC[0]};

//********************//

assign Sout={product[0][0][0:63],product[1][0][0:63],product[2][0][0:63],product[3][0][0:63],product[4][0][0:63],

             product[0][1][0:63],product[1][1][0:63],product[2][1][0:63],product[3][1][0:63],product[4][1][0:63],

             product[0][2][0:63],product[1][2][0:63],product[2][2][0:63],product[3][2][0:63],product[4][2][0:63],

             product[0][3][0:63],product[1][3][0:63],product[2][3][0:63],product[3][3][0:63],product[4][3][0:63],

             product[0][4][0:63],product[1][4][0:63],product[2][4][0:63],product[3][4][0:63],product[4][4][0:63]};

endmodule


喜欢3
用户评论
关于作者
sola

sola 未通过人工认证

懒的都不写签名

问答
粉丝
0
关注
0
  • RV-STAR 开发板
  • RISC-V处理器设计系列课程
  • 培养RISC-V大学土壤 共建RISC-V教育生态
RV-STAR 开发板