轻量级密码GFIT介绍以及其C实现
GIFT的算法:
n={ 64,128 },k=128,r={28,40}分别为{GIFT-64,GIFT-128}。
(1) 输入n位的明文, k位的密钥.
(2) S ← SubCells(S)。Sbox GS的替换
(3) S ← PermBits(S)。从密码状态的比特位置i映射到比特位置P(i),bP(i) ← bi, ∀i ∈ {0,…,n − 1}。
(4) Ci ← f(Ci−1)。轮常数是使用6位仿射LFSR生成,其状态表示为(c5,c4,c3,c2,c1,c0)。它的更新功能定义为:(c5,c4,c3,c2,c1,c0) ← (c4,c3,c2,c1,c0,c5 ⊕ c4 ⊕ 1)。六位被初始化为零,并在被用在给定轮之前被更新。
(5) RK ← K。K = k7||k6||…||k0作为密钥状态,其中ki是16位。按k7||k6||…||k1||k0 ← k1 ≫ 2||k0 ≫ 12||…||k3||k2, 方式更新密钥状态,其中>>i 是16位字内的i位右移。
(6) S ← AddRoundKey(S,K,Ci)。1. 中间结果和Ci异或.bn-1←bn-1⊕1, b23←b23⊕c5,b19 ←b19⊕c4, b15 ←b15⊕c3, b11 ← b11⊕c2,b7 ← b7⊕c1 ,b3 ← b3⊕c0. 2. 中间结果和K异或.
(7) 重复执行(2)(3)(3)r次
(8) 输出密文C。
GIFT的流程图如下:
#include "stdafx.h"
#include<stdio.h>
#include<string.h>
#include"inttypes.h"
typedef uint8_t byte;
static const byte sbox[16] = {
0x01, 0x0a, 0x04, 0x0c,
0x06, 0x0f, 0x03, 0x09,
0x02, 0x0d, 0x0b, 0x07,
0x05, 0x00, 0x08, 0x0e
};
static byte rPx[64] = {
0,17,34,51,48,1,18,35,32,49,2,19,16,33,50,3,
4,21,38,55,52,5,22,39,36,53,6,23,20,37,54,7,
8,25,42,59,56,9,26,43,40,57,10,27,24,41,58,11,
12,29,46,63,60,13,30,47,44,61,14,31,28,45,62,15
};
void printfs(const byte*s, int j = 16)
{
for (int i = 0; i < j; i++)
{
printf("%X ", s[i]);
if (i % 4 == 3) puts("");
}
}
void Subcells(byte*s)
{
for (int i = 0; i < 16; i++)
s[i] = sbox[s[i]];
}
void Exchang(byte*s)
{
int i;
byte rowl, col, shift, rowl1;
byte g[16];
memset(g, 0, sizeof(g));
for (i = 0; i < 64; i++)
{
rowl = i / 4;
col = i % 4;
shift = 0x01;
shift <<=col;
rowl1 = rPx[i] / 4;
if (shift&s[rowl1])
g[rowl] |= shift;
}
memcpy(s, g, sizeof(g));
}
void addkeys(byte*k, byte*s)
{
int i;
byte p,shift,shift1,q,a,b;
byte tmp;
shift = 0x01;
shift1 = 0x02;
for (i = 0; i < 16; i++)
{
int j = i / 8;
int m = i;
if (i >= 8) m = i - 8;
p = k[j];
a = (p >> m)&shift;
q = k[j + 2];
if ((i == 0) | (i == 8)) b = (q << 1)&shift1;
else b = (q >> (m - 1)&shift1);
if (a== shift)
{
if ((s[i] & shift) == a)
s[i] = s[i] & 0x0e;
else
s[i] |= (s[i] & shift) ^ a;
}
if (b == shift1)
{
if ((s[i] & shift1) == b)
s[i] = s[i] & 0x0d;
else
s[i] |= (s[i] & shift1) ^ b ;
}
}
}
void Updatekeys(byte*k)
{
byte tmp[16], tmp1[16];
for (int i = 0; i < 16; i++)
tmp[i] =tmp1[i] = k[i];
k[15] = ((tmp[3] >> 2) | (tmp[2] << 6)) & 0xff;
k[14] = ((tmp1[3] << 6) | (tmp1[2] >> 2)) & 0xff;
k[13] = ((tmp[1] << 4) | (tmp[0] >> 4)) & 0xff;
k[12] = ((tmp1[1] >> 4) | (tmp1[0] << 4)) & 0xff;
for (int j = 0; j < 12; j++) k[j] = tmp[j + 4];
}
void UpdateConstant(byte*c)
{
byte a, c5, c4, c0;
a = *c;
c5 = (a >> 5) & 0x01;
c4 = (a >> 4) & 0x01;
c0 = c5 ^ c4 ^ 1;
*c= ((*c<< 1) & 0x3f) | c0;
}
void addLFSR(byte*s, byte*c)
{
byte a, b;
byte shift = 0x08;
a = *c;
for (int i = 0; i < 6; i++)
{
b = ((a >> i) << 3)&shift;
if (b == shift)
{
if ((s[i] & shift) == b)
s[i] = s[i] & 0x07;
else s[i] |= (s[i] & shift) ^ b;
}
}
if (s[15] & shift)
s[15] = s[15] & 0x07;
else s[15] |= (s[15] & shift) ^ shift;
}
void Ercrypt(byte*s, byte*k)
{
byte *Constants;
byte a = 0x00;
Constants = &a;
int i;
for (i = 0; i < 28; i++)
{
Subcells(s);
Exchang(s);
addkeys(k, s);
UpdateConstant(Constants);
addLFSR(s, Constants);
Updatekeys(k);
}
}
int main()
{
byte k[16], p[16];
for (int i = 0; i < 16; i++)
p[i] = 0x0f;
for (int i = 0; i < 16; i++)
k[i] = 0xff;
puts("Plaintext:"); printfs(p); puts("");
puts("key:"); printfs(k, 16); puts("");
puts("Ercrypt:");
Ercrypt(p, k);
printfs(p);
return 0;
}