最近小编在项目中遇到了Rijndael算法进行加密的场景,使用它作为一种对称加密的手段防御网络攻击,下面说一下他的流程,部分图解是手写然后扫描出来的。
Rijndael算法是AES算法的一种,是一种分组加密模式,也就是说把明文分成定长的若干段,用定长的密钥进行加密计算。下图中绿色矩阵代表k密钥(key),黄色矩阵代表明文或者状态(state)。
Rijndael流程是由四种基本的运算组成的,这四种运算以特定的顺序进行循环,对初始的明文和密钥进行计算,数据的形式是矩阵,矩阵中的每一个元素都是一个字节(8 bits)的16进制表示,比如128bits的数据用4×4的矩阵表示,那么每一个元素就占有8 bits,也就是一个字节,分成上半字节(4 bits)和下半字节(4 bits),就得到了诸如"a0", "c6"此类的数据,那么128bits的明文和密钥就可以用矩阵表示并且进行计算。
首先介绍总体流程,其中具有循环:
中间循环模块的循环次数和密钥与密文块的长度有关:128bits密钥--10轮循环、192bits--12轮循环、256bits--14轮循环。
可以看到子环节有四种:subBytes, shiftRows, mixColumns, addRoundKey,下面手画的图中分别用[1], [2], [3], [4]方框去在图中进行标记。值得注意的是初始的处理和尾轮循环都是不太一样的,不是完整的四个子环节。
【1】将元素的高半字节和低半字节作为x y坐标,映射S-box中的元素,进行矩阵的整体替换
【2】将第i行(从0行开始)的元素向左推,被推出的元素放在右侧
S-box的映射表如下:
【3】和MDS矩阵进行点乘运算
【4】得到的矩阵每一列和key的每一列进行异或运算得到新的矩阵
需要注意的是每次经过步骤【4】,使用的key都是不同的,初始的key经过计算不断的变化,这个过程也叫做计算子密钥:
计算子密钥的第一列的步骤如下:
其中向量[8a, 84, eb, 01]由来是:key的最后一列[09, cf, 4f, 3c] --> [cf, 4f, 3c, 09] -->S-box映射。
中间的步骤就可以是:
每一个sub key的第一列都是这样的出的,比如第二个sub key的首列:
在横向的长矩阵中依次截取4×4的block就得到了每一轮用到的key,替换到步骤【4】即可。
最后引入一段实现rijndael加密的python代码,并不涉及到对核心环节的复现,只是一种实现的方式和范例:
from Crypto.Cipher import AES
import binascii
KEY = binascii.unhexlify('xxx')
plaintext = binascii.unhexlify('yyy')
rijn = AES.new(KEY, AES.MODE_ECB)
ciphertext = rijn.encrypt(plaintext)
result = binascii.hexlify(ciphertext).decode('utf-8')
输入输出的参数可以参照一些工具网站,可以提供加密的计算服务