grain算法c语言代码实现与分析
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
流密码Grain算法实现分析
作为公布的为数不多的序列密码算法(大概有8种)版本之一,Grain算法是比较适合资源受限场合的信息加密,像移动通信采用的加密算法。
下面对Grain算法V1版本的实现作下相关分析,希望在商业中信息安全应用有所帮助。
下面是Grain算法V1版本的标准C程序代码,具体分析及算法的其他实现方法在随后会提及:
#ifndef GRAIN_H
#define GRAIN_H
#include "ecrypt-sync.h"
#define INITCLOCKS 160
#define N(i) (ctx->NFSR[80-i])
#define L(i) (ctx->LFSR[80-i])
#define X0 (ctx->LFSR[3])
#define X1 (ctx->LFSR[25])
#define X2 (ctx->LFSR[46])
#define X3 (ctx->LFSR[64])
#define X4 (ctx->NFSR[63])
static const u8 NFTable[1024]= {0,1,0,0,1,0,1,1,1,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,0,1,0,0,0,1,0,1,
1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,1,1,0,1,1,0,1,0,0,0,1,0,0,0,1,0,1,
1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,1,0,1,1,1,0,1,0,
0,1,0,0,1,0,1,1,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,1,1,0,1,1,1,0,1,0,
1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,1,0,1,1,1,0,1,0,
0,1,0,0,1,0,1,1,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,1,1,0,1,1,1,0,1,0,
0,1,0,0,1,0,1,1,1,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,0,1,0,0,0,1,0,1,
1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,1,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,0,
1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,1,0,1,1,1,0,1,0,
0,1,0,0,1,0,1,1,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,1,1,0,1,1,1,0,1,0,
0,1,0,0,1,0,1,1,1,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,0,1,0,0,0,1,0,1,
1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,1,1,0,1,1,0,1,0,0,0,1,0,0,0,1,0,1,
0,1,0,0,1,0,1,1,1,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,0,1,0,0,0,1,0,1,
1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,1,0,1,1,1,0,1,0,
0,1,0,0,1,0,1,1,1,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,0,1,0,0,0,1,0,1,
1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,1,0,1,1,0,1,0,1,
0,1,0,0,1,0,1,1,1,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,0,1,0,0,0,1,0,1,
1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,1,1,0,1,1,0,1,0,0,0,1,0,0,0,1,0,1,
1,0,1,1,0,1,0,0,0,0,0,1,1,1,1,0,0,1,0,0,1,0,1,1,1,1,1,0,1,1,1,1,
0,1,0,0,1,0,1,1,1,1,1,0,0,0,0,1,0,1,0,0,1,0,1,1,1,1,1,0,1,1,1,1,
1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,1,0,1,1,1,0,1,0,
0,1,0,0,1,0,1,1,1,0,1,1,0,1,0,0,0,1,0,0,1,0,1,1,1,0,1,1,1,0,1,0,
0,1,0,0,1,0,1,1,1,1,1,0,0,0,0,1,1,0,1,1,0,1,0,0,0,0,0,1,0,0,0,0,
1,0,1,1,0,1,0,0,0,0,0,1,1,1,1,0,1,0,1,1,0,1,0,0,0,0,0,1,1,1,1,1,
0,1,0,0,1,0,0,0,1,0,1,1,0,1,1,1,1,0,1,1,0,1,1,1,0,1,0,0,0,1,1,0,
1,0,1,1,0,1,1,1,0,1,0,0,1,0,0,0,1,0,1,1,0,1,1,1,0,1,0,0,0,1,1,0,
1,0,1,1,0,1,1,1,0,0,0,1,1,1,0,1,0,1,0,0,1,0,0,0,1,1,1,0,1,1,0,0,
0,1,0,0,1,0,0,0,1,1,1,0,0,0,1,0,0,1,0,0,1,0,0,0,1,1,1,0,1,1,0,0,
1,0,1,1,0,1,1,1,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,0,1,0,1,1,1,0,0,1,
0,1,0,0,1,0,0,0,1,0,1,1,0,1,1,1,1,0,1,1,0,1,1,1,0,1,0,0,0,1,1,0,
1,0,1,1,0,1,1,1,0,0,0,1,1,1,0,1,0,1,0,0,1,0,0,0,1,1,1,0,1,1,0,0,
1,0,1,1,0,1,1,1,0,0,0,1,1,1,0,1,0,1,0,0,1,0,0,0,1,1,1,0,0,0,1,1};
static const u8 boolTable[32] = {0,0,1,1,0,0,1,0,0,1,1,0,1,1,0,1,1,1,0,0,1,0,1,1,0,1,1,0,0,1,0,0};
#endif
#include "grain-v1.h"
void ECRYPT_init(void){}
u8 grain_keystream(ECRYPT_ctx* ctx) {
u8 i,NBit,LBit,outbit;
outbit = N(79)^N(78)^N(76)^N(70)^N(49)^N(37)^N(24)^boolTable[(X4<<4) | (X3<<3) | (X2<<2) | (X1<<1) | X0];
NBit=L(80)^N(18)^N(66)^N(80)^NFTable[(N(17)<<9) | (N(20)<<8) | (N(28)<<7) | (N(35)<<6) | (N(43)<<5) | (N(47)<<4) | (N(52)<<3) | (N(59)<<2) | (N(65)<<1) | N(71)];
LBit=L(18)^L(29)^L(42)^L(57)^L(67)^L(80);
for (i=1;i<(ctx->keysize);++i) {
ctx->NFSR[i-1]=ctx->NFSR[i];
ctx->LFSR[i-1]=ctx->LFSR[i];
}
ctx->NFSR[(ctx->keysize)-1]=NBit;
ctx->LFSR[(ctx->keysize)-1]=LBit;
return outbit;
}
void ECRYPT_keysetup(
ECRYPT_ctx* ctx,
const u8* key,
u32 keysize,
u32 ivsize)
{
ctx->p_key=key;
ctx->keysize=keysize;
ctx->ivsize=ivsize;
}
void ECRYPT_ivsetup(
ECRYPT_ctx* ctx,
const u8* iv)
{
u32 i,j;
u8 outbit;
for (i=0;i<(ctx->ivsize)/8;++i) {
for (j=0;j<8;++j) {
ctx->NFSR[i*8+j]=((ctx->p_key[i]>>j)&1); ctx->LFSR[i*8+j]=((iv[i]>>j)&1);
}
}
for (i=(ctx->ivsize)/8;i<(ctx->keysize)/8;++i) { for (j=0;j<8;++j) {
ctx->NFSR[i*8+j]=((ctx->p_key[i]>>j)&1); ctx->LFSR[i*8+j]=1;
}
}
for (i=0;i<INITCLOCKS;++i) {
outbit=grain_keystream(ctx);
ctx->LFSR[79]^=outbit;
ctx->NFSR[79]^=outbit;
}
}
void ECRYPT_keystream_bytes(
ECRYPT_ctx* ctx,
u8* keystream,
u32 msglen)
{
u32 i,j;
for (i = 0; i < msglen; ++i) {
keystream[i]=0;
for (j = 0; j < 8; ++j) {
keystream[i]|=(grain_keystream(ctx)<<j); }
}
}
void ECRYPT_encrypt_bytes( ECRYPT_ctx* ctx,
const u8* plaintext,
u8* ciphertext,
u32 msglen)
{
u32 i,j;
u8 k;
for (i = 0; i < msglen; ++i) {
k=0;
for (j = 0; j < 8; ++j) {
k|=(grain_keystream(ctx)<<j);
}
ciphertext[i]=plaintext[i]^k;
}
}
void ECRYPT_decrypt_bytes( ECRYPT_ctx* ctx,
const u8* ciphertext,
u8* plaintext,
u32 msglen)
{
u32 i,j;
u8 k=0;
for (i = 0; i < msglen; ++i) {
k=0;
for (j = 0; j < 8; ++j) {
k|=(grain_keystream(ctx)<<j);
}
plaintext[i]=ciphertext[i]^k;
}
}。