
0 Simon简介
详细文档请直接阅读参考文献[1]。
Simon是由NSA设计的轻量级分组密码算法(LIGHTWEIGHT BLOCK CIPHER)。主要应用于硬件或软件条件受限(例如:芯片面积要求小、微处理器、低功耗等),同时对安全有一定需求的低端设备。相比DES、AES等,Simon在结构上相对简单,轮函数操作也不复杂。因此在计算速度和资源消耗上更有优势,更能适应软硬件条件受限的情况。
为了适应不同的场合,Simon提供了不同的方案,如图0.
图0 Simon密码族
图1 Simon轮函数结构图
其中,
block size : 明文块大小,比特位;
key size : 初始密钥大小,比特位;
word size : "字"大小,比特位;
key words : 初始密钥包含"字"的个数;
const seq : 计算轮密钥应该使用的z的值;
rounds : 加解密的轮数。
1 算法流程
Simon的整个流程比较简单,接下来分别对加解密轮函数和密钥编排算法进行介绍。
1.1 轮加密
每一轮的操作如图1。明文被分成两个"字",每个"字"的二进制位数都为n(即word size),Xi+1和Xi分别表示高位部分和低位部分(个人认为,这个没有特别要求,Xi+1也可以表示低位、Xi表示高位部分,只要加解密按照同样的顺序即可。为了叙述统一,本文按照Xi+1表示高位、Xi表示低位)。
每轮的加密主要涉及到3种操作,如图2所示,分别是异或、按位与和循环左移(如果j是负数则表示循环右移)。每轮加解密的过程用公式表示如图3,其中x对应Xi+1、y对应Xi、k为轮密钥。
图2 Simon运算符号
图3 Simon轮加解密公式
在C++实现中,按位异或和与都有直接的操作符,对于循环移位可以按照如下方法实现。将x循环左移i(i>=0)位,假设x对应的二进制位数为n,则可以表示为: (x<<i) | (x>>(n-i))。当然,x应该是无符号的数,不然会出错。
/* * 加密后的低32位是明文的高32位 */ tempCipherLower = plainText[]; tempCipherHigher = plainText[] ^ keys[i] ^ ( ((plainText[]<<)|(plainText[]>>(SIMON_WORD_SIZE-))) & ((plainText[]<<)|(plainText[]>>(SIMON_WORD_SIZE-))) ) ^ ((plainText[]<<)|(plainText[]>>(SIMON_WORD_SIZE-))); /* * 重新将加密的结果复制到plainText中 */ plainText[] = tempCipherHigher; plainText[] = tempCipherLower;
1.2 密钥编排
密钥编排算法如图4,其中m表示的是原始密钥中"字"的个数。
图4 密钥编排算法
c为一个常数,它的二进制位数为n,最低两位为0,其余高位为1。
z是一个常数数组,值如图5,在每种情况下z的取值都是固定的(见图0),每轮加解密时只取一个比特位参与运算。
ki、ki+1、ki+2等都是轮密钥。
I表示不进行移位。
图5 z
C++代码实现如下(只包含block size为64,key size为96和128的两种情况):
/* * Simon:计算密钥,字大小为32 * inputKey:初始的密钥 * keys:计算后得到的每轮密钥 */ void setSimonKeys32 ( unsigned int * inputKey, unsigned int * keys ) { /* * 算法中的常数c,大小为2^n - 4,其中n是字的长度,即SIMON_WORD_SIZE * 转化为二进制,即最低两位为0,其它位全为1 */ unsigned int c = 0xfffffffc; int i; ; i < SIMON_KEY_WORDS; i++ ) { keys[i] = inputKey[i]; } /* * 求解后面轮的密钥 * 先求其它的异或,最后求Zji,如果为1则对最低位进行修改,否则不变 */ ) { ; i < SIMON_ROUNDS-SIMON_KEY_WORDS; i++ ) { keys[i+SIMON_KEY_WORDS] = c ^ keys[i] ^ ((keys[i+]>>) | (keys[i+]<<(SIMON_WORD_SIZE-))) ^ ((keys[i+]>>) | (keys[i+]<<(SIMON_WORD_SIZE-))); // SIMON_WORD_SIZE为32时,无论SIMON_KEY_WORDS为3还是4,周期都是62 ] == ) { keys[i+SIMON_KEY_WORDS] ^= 0x1; } } } ) { // int cycle = (SIMON_SEQUENCE_NUMBER == 0 || SIMON_SEQUENCE_NUMBER == 1)?31:62; unsigned int temp = 0x00000000; ; i < SIMON_ROUNDS-SIMON_KEY_WORDS; i++ ) { temp = ((keys[i+]>>) | (keys[i+]<<(SIMON_WORD_SIZE-))) ^ keys[i+]; keys[i+SIMON_KEY_WORDS] = c ^ keys[i] ^ temp ^ ((temp>>) | (temp<<(SIMON_WORD_SIZE-))); ] == ) { keys[i+SIMON_KEY_WORDS] ^= 0x00000001; } } } }
参考文献
[1] Beaulieu R, Shors D, Smith J, et al. The SIMON and SPECK Families of Lightweight Block Ciphers[J]. IACR Cryptology ePrint Archive, 2013, 2013: 404.