这篇文章带来ECE111第六节课的Slides以及自己的一些补充。
该课程的网站如下:
在开始本节课之前”鉴赏“一下Project2的示例代码:
分析此类代码首先仍然按我之前说的方法,先看状态机:
- 一共5个状态,IDLE状态以及步骤1~4状态。
- 当start信号拉高的时候,会跳到STEP1状态。该状态初始化读请求,需要把we信号拉低,同时将读地址赋值为:输入的原始读地址+count。然后跳到状态2
- 状态2等待内存模型输出的结果,接着跳到状态3。
- 状态3初始写命令,需要将we信号拉高,同时将写地址赋值为:输入的原始写地址+count。同时将之前读回来的数据进行字节旋转,再将count加1。代表一次完整的读写操作。然后跳到状态4
- 状态4首先判断count是否与定义的size大小一致,如果是的话。则代表已经完成了所有的运算,将done信号拉高,然后跳到IDLE状态。否则跳到步骤1(状态2),重复上述的操作。
上面的代码逻辑非常清晰,事实上它将读写操作划分为一个一个的状态,非常易于实现。这种代码对于初学者而言其实是很容易接收的,因为大家实际上可以用软件亦或者说人的思维方式思考这一问题,不需要考虑实际的硬件架构。这种编码方式希望大家好好掌握,对于一步一步实现的,大部分都可以通过状态机实现。这种方式不一定好,但是它简单可控,易于维护。
大家再思考一下,上面的状态有没有冗余状态?实际上是有的,对于状态4的判断操作,实际上可以放在状态3去做。我们先写数据,然后就可以判断count是否等于size,从而跳转到STEP1或IDLE态。代码在这个链接,图片我就不贴了,http://cwcserv.ucsd.edu/~billlin/classes/ECE111/examples/br1.sv。此外还可以流水线的方式读写,从而掩盖SRAM的输出延迟。也就是开始的状态2,等待SRAM输出结果,这一个周期我们实际上什么都没有干,那我们是不是可以再读一次?下一个时钟周期SRAM输出了结果,同时输入的地址也发生了变化。那我们就可以连着写两次了,似乎节省了一个时钟周期。代码大家自行研究一下,分析思路和上面的分析思路是类似的。http://cwcserv.ucsd.edu/~billlin/classes/ECE111/examples/br2.sv
接下来进入本节课的正题,Project3:SHA256算法。
相信大家或多或少,都听到过加密、哈希、数字签名之类的名词。今天就带大家自己动手实现一个哈希算法-SHA256。SHA的意思为Secure Hash Algorithm,安全哈希算法,或者叫安全散列算法。哈希这个词语很有迷惑性,我更加愿意称之为散列算法。即从一组数据散列到另外一组数据。SHA系列算法由美国国家安全局制定,从最初的SHA0到SHA1到SHA224再到SHA256,此外还有SHA384和SHA512。其中SHA0已经没有人使用了,SHA1算法目前仍然有一些地方在使用,尽管SHA1已经没那么安全了(更多的资料大家可以自己搜索)。另外值得注意的是,很多地方把SHA系列算法称为加密算法,严格地说它只是单向散列算法,不能称之为加密算法。
我们的目标是对于任意输入的信息(message),计算它的哈希值(对于给定的输入,它的哈希值是一定的)。message可以是任意的东西。
SHA-256会返回256比特的哈希值,或者称之为数据摘要或强校验和。然后是一些数据经过SHA256的计算结果(再次提醒,这个数据是广义的数字序列,一串文字,一个图片,一部电影,mp3格式的音乐等都是一串数据)。
这张图告诉我们,对于输入而言,发生很小的改变,对于计算得到的哈希值会发生巨大的变化。这一特性称为无序性。
然后介绍了一下哈希算法的应用之一:检验文件的完整性。软件制造商想要确保可执行文件被用户接收而没有修改,把文件发给用户,同时将哈希值公布到NY times(纽约时代?不知道是啥,应该是个公共区域)。目标是完整性,而不是保密!用户接收文件的时候对比哈希值就知道文件有没有被篡改。这是因为很难找到一个别的文件,两个哈希值是一模一样的,这称为哈希碰撞(比特币获取的原理就是哈希碰撞)。
同时还可以用来鉴权,比如Alice给Bob(熟悉的名字他来了)发消息,希望确保没有人在传输过程中修改消息。那就把哈希值一起发送。接收方一对比就知道消息有没有被修改了。
然后介绍了SHA256的要求:
- 输入的消息必须小于2的64次方比特(这实际上不是什么问题,因为...大家可以算一下这个数有多大)
- 输入的消息是以512bit为一个block来循序的处理的
- 数据摘要是256比特
然后介绍了SHA-256算法,其步骤如下
- 步骤一,填充比特。首先在数据的末尾填充一个“1”。然后填充“0”直到数据长度对512取模为448,即数据长度为512N+448(N=0,1,2...)。
- 步骤2,填充64bit的数据,该数据为message的长度(注意是原始的长度,如上图的900),到此为止,整个的长度为512的正整数倍。