文档库 最新最全的文档下载
当前位置:文档库 › IC课设报告 (1)

IC课设报告 (1)

SHA IP的设计与实现

姓名:

学号:

班级:

院系:控制系

专业:自动化

同组人姓名:

目录

1.题目描述 (3)

2.SHA1算法. (3)

2.1.概述 (3)

SHA-1算法简介

2.2 SHA1算法描述 (4)

2.2.1 补位

2.2.2 补长度

2.2.3 使用的常量

2.2.4 需要使用的函数

2.2.5 计算消息摘要

2.2.6 一个实例流程图

3. 模块设计 (8)

3.1精确模块图

3.2 输入输出描述

4.综合后的整体电路图 (11)

5.源码与注释 (19)

5.1 sha1主module

5.25.2 定义sha1算法的循环代码module

6.心得体会与建议 (27)

1.题目描述

实现一个SHA(Secure Hash Algorithm) IP core ,支持SHA-1(160) 或者

SHA-2(256/512) 使用32-bit I/O bus interface。

要求基于Verilog HDL完成电路设计,并完成电路综合。

指导老师:郑朝霞(87541768,zxzheng@https://www.wendangku.net/doc/7512934961.html,)

助教:丁明鹏159********

2. 2.1 概述

SHA-1算法简介

消息认证作为一种重要的安全技术如今已被广泛地应用于网络信息交换领域,它的根本作用是允许通信的当事人验证所接受的消息为可信消息。如果消息、文件、文档或者其他的数据集合是真实的数据并且来自所声称的数据源,那么称这些数据集合是可信的。而在消息认证技术中通常都会用到一类特殊的数学算法-哈希算法,它占有极其重要的地位。哈希算法也即散列算法,其作用是对任何不定长的比特串(称为消息)计算出一个定长的比特串(称为消息摘要

或散列值)。

目前常见的哈希算法有MD5、SHA-1和RIPEMD-160,而国内更倾向于MD5和SHA-1。就当前的情况来看,SHA-1由于其安全强度及运算效率方面的优势已经成为使用最为广泛的哈希算法了。

安全哈希算法(Secure Hash Algorithm)主要适用于数字签名标准(Digital Signature Standard DSS)里面定义的数字签名算法(Digital Signature Algorithm DSA)。对于长度小于2^64位的消息,SHA1会产生一个160位的消息摘要。当接收到消息的时候,这个消息摘要可以用来验证数据的完整性。在传输的过程中,数据很可能会发生变化,那么这时候就会产生不同的消息摘要。SHA1有如下特性:不可以从消息摘要中复原信息;两个不同的消息不会产生同样的消息摘要。

2.2 SHA1算法描述

在SHA1算法中,我们必须把原始消息(字符串,文件等)转换成位字符串。SHA1算法只接受位作为输入。假设我们对字符串“abc”产生消息摘

要。首先,我们将它转换成位字符串如下:01100001 01100010 01100011―――――――――――――…a?=97 …b?=98 …c?=99这个位字符串的长度为24。下面我们需要5个步骤来计算消息摘要MAC。

2.2.1 补位

消息必须进行补位,以使其长度在对512取模以后的余数是448。也就是说,(补位后的消息长度)%512 = 448。即使长度已经满足对512取模后余数是448,补位也必须要进行。补位是这样进行的:先补一个1,然后再补0,直到长度满足对512取模后余数是448。总而言之,补位是至少补一位,最多补512位。还是以前面的“abc”为例显示补位的过程。原始信息:01100001 01100010 01100011补位第一步:01100001 01100010 01100011 1首先补一个“1”补位第二步:01100001 01100010 01100011 10…..0然后补423个“0”我们可以把最后补位完成后的数据用16进制写成下面的样子61626380 00000000 00000000 00000000 00000000 00000000 00000000 0000000000000000 00000000 00000000 0000000000000000 00000000现在,数据的长度是448了,我们可以进行下一步操作。

2.2.2 补长度

所谓的补长度是将原始数据的长度补到已经进行了补位操作的消息后面。通常用一个64位的数据来表示原始消息的长度。如果消息长度不大于2^64,那么第一个字就是0。在进行了补长度的操作以后,整个消息就变成下面这样了(16进制格式)61626380 00000000 00000000 00000000 00000000 00000000 00000000 0000000000000000 00000000 00000000 0000000000000000 00000000 00000000 00000018如果原始的消息长度超过了512,我们需要将它补成512的倍数。然后我们把整个消息分成一个一个512位的数据块,分别处理每一个数据块,从而得到消息摘要。

2.2.3 使用的常量

一系列的常量字K(0), K(1), ... , K(79),如果以16进制给出。它们如下:Kt = 0x5A827999 (0 <= t <= 19)Kt = 0x6ED9EBA1 (20 <= t <= 39) Kt = 0x8F1BBCDC (40 <= t <= 59)Kt = 0xCA62C1D6 (60 <= t <= 79).

2.2.4 需要使用的函数

在SHA1中我们需要一系列的函数。每个函数ft (0 <= t <= 79)都操作32位字B,C,D并且产生32位字作为输出。ft(B,C,D)可以如下定义ft(B,C,D) = (B AND C) or ((NOT B) AND D) ( 0 <= t <= 19)ft(B,C,D) = B XOR C XOR D (20 <= t <= 39)ft(B,C,D) = (B AND C) or (B AND D) or (C AND D) (40 <= t <= 59)ft(B,C,D) = B XOR C XOR D (60 <= t <= 79).

2.2.5 计算消息摘要

必须使用进行了补位和补长度后的消息来计算消息摘要。计算需要两个缓冲区,每个都由5个32位的字组成,还需要一个80个32位字的缓冲区。第一个5个字的缓冲区被标识为A,B,C,D,E。第二个5个字的缓冲区被标识为H0, H1, H2, H3, H4。80

个字的缓冲区被标识为W0, W1,..., W79另外还需要一个一个

字的TEMP缓冲区。为了产生消息摘要,在第4部分中定义的16个字的数据块M1, M2,..., Mn会依次进行处理,处理每个数据块Mi 包含80个步骤。在处理每个数据块之前,缓冲区{Hi} 被初始化为下面的值(16进制)H0 = 0x67452301H1 =

0xEFCDAB89H2 = 0x98BADCFE H3 = 0x10325476H4 = 0xC3D2E1F0.现在开始处理M1, M2, ... , M n。为了处理Mi,需要进行下面的步骤(1). 将Mi 分成16 个字W0, W1, ... ,

W15, W0 是最左边的字(2). 对于t = 16 到79 令Wt =

S1(Wt-3 XOR Wt-8 XOR Wt- 14 XOR Wt-16).(3). 令 A = H0, B = H1, C = H2, D = H3, E = H4.(4) 对于t = 0 到79,执行下面的循环TEM P = S5(A) + ft(B,C,D) + E + Wt + Kt; E = D;

D = C; C = S30(B); B = A; A = TEMP;(5). 令H0 = H0 + A, H1 = H1 + B, H2 = H2 + C, H3 = H3 + D, H4 = H4 + E.在处理完所有的Mn, 后,消息摘要是一个160位的字符串,以下面的顺序标识H0 H1 H2 H3 H4.对于SHA256,SHA384,SHA512。你也可以用相似的办法来计算消息摘要。对消息进行补位的算法完全是一样的。

2.2.6

一个实例流程图

3.模块设计

3.1 精确模块图

数据填充模块,Wt生成模块,Sha1压缩模块,工作模式控制模块,结果输出模块

Data in Data in

工作模式控

制模块

复位信号控制模块

数据填充

模块

Wt生成

模块

压缩模块输出模块

Data

out

3.2 输入输出描述

输入:clk_in,接入系统时钟,作为内部模1512计数器和模6计数器的时钟。

输出:c1,模1512计数器的进位输出,当计数器计满一次时,c1翻转一次;

c2,模126计数器的进位输出,当计数器计满一次时,c2翻转一次,因为模126计数器的时钟是基准时钟的6倍,所以c2实际上是756

个时钟周期翻转一次;

cn1,模1512计数器的输出,数据宽度为11位,输出范围为0到1511;

cn2,模6计数器的输出,数据宽度为3位,输出范围为0到5;

cn3,模126计数器的输出,数据宽度为7位,输出范围为0到125。

3.3部分模块图。

4.Quartus II综合后的整体电路图

5. 结果仿真分析

仿真编译成功

输入01100001 01100010 01100011二进制代表“abc”输出160位码。

6. 源码与注释

5.1 sha1主module

module sha1_exec(clk, reset, start, data_in, load_in, cv,

use_prev_cv, busy, out_valid, cv_next);

input clk, reset; // Global clock and synchronous reset时钟信号和重置信号

input start;//开始信号

input [31:0] data_in;

input load_in;

input [159:0] cv; //输出摘要

input use_prev_cv; //上一次的输出摘要

output busy; //正在工作

output out_valid; //输出有效

output [159:0] cv_next; //迭代过程中摘要

reg busy;

reg out_valid;

reg [6:0] rnd_cnt_d; //计算迭代轮数,2^7=128>80 wire [6:0] rnd_cnt_q; //标记是第几轮迭代

wire [159:0] rnd_d; // 迭代输出途径

wire [159:0] rnd_q;

wire [159:0] sha1_round_wire; //每轮迭代的数出摘要

wire [159:0] cv_d; // 保存添加数据的迭代结果

wire [159:0] cv_q; // 上次循环迭代结果

wire [159:0] cv_next_d; // 保存结果

wire [159:0] cv_next_q;

// 状态常量的定义parameter IDLE = 2'b00; //闲置

parameter CALC = 2'b01; //计算状态

parameter V ALID_OUT = 2'b10; //有效输出

parameter V ALID_OUT2 = 2'b11;

wire [1:0] state;

reg [1:0] next_state;

// 源数据块中的数据,以512bit为单位wire [511:0] w_d;

wire [511:0] w_q;

wire [511:0] w_temp;

wire [31:0] w;

//生成源数据块所对应的字(32位)wire [31:0] w_gen_temp = w_temp[511:480] ^ w_temp[447:416] ^

w_temp[255:224] ^ w_temp[95:64]; //

wire [31:0] w_gen = {w_gen_temp[30:0], w_gen_temp[31]}; // 选择中间的迭代结果

assign w_d = ((load_in == 1'b1) ? w_temp :

((rnd_cnt_q ==7'd15) ? w_temp :

{w_gen, w_temp[479:0]})); //当load_in有效时,选择载入信息

// 源数据左移32位assign w_temp = (state == CALC) ? {w_q[479:0], w_q[511:480]} :

((load_in == 1'b1) ? {w_q[479:0], data_in} : w_q);

// 直接载入寄存器输出

assign w = w_q[511:480];

sha1_round sha1_round(.cv_in(rnd_q), .w(w), .round(rnd_cnt_q),

.cv_out(sha1_round_wire));

// 接受输入摘要信息assign rnd_d = ((state == CALC) ? sha1_round_wire :

(use_prev_cv == 1'b1) ? cv_next_q : cv);

assign cv_d = ((state == CALC) ? cv_q :

(use_prev_cv == 1'b1) ? cv_next_q : cv);

// 计算最终迭代,得到最终的摘要结果

assign cv_next_d = (state == V ALID_OUT) ?

({cv_q[159:128] + rnd_q[159:128],

cv_q[127:96] + rnd_q[127:96],

cv_q[95:64] + rnd_q[95:64],

cv_q[63:32] + rnd_q[63:32],

cv_q[31:0] + rnd_q[31:0]}) :

(cv_next_q);

// 最终摘要结果传递assign cv_next = cv_next_q; // 主循环

always @(state or start or rnd_cnt_q)

Begin //置初值out_valid = 1'b0; //输出有效置零

busy = 1'b0; //工作状态置零

rnd_cnt_d = 7'b0000000; //迭代轮数为零

case (state)

IDLE : begin

out_valid = 1'b0;

rnd_cnt_d = 7'b0000000;

if (start) begin

busy = 1'b1;

next_state = CALC;">

end

else begin

busy = 1'b1;

next_state = IDLE;

end

end // 闲置状态

CALC : begin

busy = 1'b1;

out_valid = 1'b0;

if (start) begin

next_state = IDLE;

rnd_cnt_d = 7'd0000000;

end

else if (rnd_cnt_q == 7'd79) begin

next_state = V ALID_OUT;

rnd_cnt_d = 7'd0000000;

end

else begin

next_state = CALC;

rnd_cnt_d = rnd_cnt_q + 7'd0000001;

end

end // 计算状态

V ALID_OUT : begin

busy = 1'b1;

out_valid = 1'b0;

// 允许使用output结果

if (start) begin

next_state = IDLE;

rnd_cnt_d = 7'd0000000;

end else begin

next_state = V ALID_OUT2;

end

end

V ALID_OUT2 : begin

busy = 1'b0;

out_valid = 1'b1;

if (start) begin

next_state = CALC;

end

else begin

next_state = IDLE;

end

end

default : begin

next_state = IDLE;

end

endcase

end

dffhr #(7) rnd_cnt_reg (.d(rnd_cnt_d), .q(rnd_cnt_q),

.clk(clk), .r(reset));

dffhr #(2) state_reg (.d(next_state), .q(state),

.clk(clk), .r(reset));

dffhr #(512) w_reg (.d(w_d), .q(w_q), .clk(clk), .r(reset));

dffhr #(160) cv_reg (.d(cv_d), .q(cv_q), .clk(clk), .r(reset));

dffhr #(160) rnd_reg (.d(rnd_d), .q(rnd_q), .clk(clk), .r(reset));

dffhr #(160) cv_next_reg (.d(cv_next_d), .q(cv_next_q),.clk(clk), .r(reset));

endmodule

5.2 定义sha1算法的循环代码module

module sha1_round (cv_in, w, round, cv_out);

input [159:0] cv_in; //定义输入端口

input [31:0] w; //定义输入端口

input [6:0] round; //定义输入端口

output [159:0] cv_out; //定义输出端口

reg [31:0] k;

reg [31:0] f;

wire [31:0] a_shift;

wire [31:0] b_shift;

wire [31:0] add_result;

wire [31:0] a = cv_in[159:128];

wire [31:0] b = cv_in[127:96];

wire [31:0] c = cv_in[95:64];

wire [31:0] d = cv_in[63:32];

wire [31:0] e = cv_in[31:0];

always @(round) //创建四个平行

相关文档
相关文档 最新文档