文章目錄
- 1. 分組密碼(Twine)
- 1.1 加解密方式
- 1.1.1 加密
- 1.1.2 密鑰生成演算法
- 1.1.3 解密
- 1.1.4 全部代碼
- 1.2. 分組密碼的模式
- 1.2.1 ECB模式
- 1.2.2 CBC模式
- 1.2.3 CFB模式
- 1.2.4 OFB模式
- 1.2.5 CTR模式
- 2.序列密碼
如圖,對稱加密演算法是應用較早的加密演算法,技術成熟,在對稱加密演算法中,資料發信方將明文和加密密鑰一起經過特殊加密演算法處理后,使其變成復雜的加密密文發送出去,收信方收到密文后,若想解讀原文,則需要使用加密用過的密鑰及相同演算法的逆演算法對密文進行解密,才能使其恢復成可讀明文,具有演算法公開、計算量小、加密速度快、加密效率高等特點,
1. 分組密碼(Twine)
Twine是由Tomoyasu Suzaki,Kazuhiko Minematsu, Sumio Morioka和Eita Kobayashi在2011年的ECRYPT輕量級密碼會議上首次提出的,并發表在2012年的SAC會議上,它的分組長度是64位元,密鑰長度有80位元和128位元兩個版本,其采用廣義的Feistel結構(Generalized Feistel Structure,簡稱GFS),并由36輪輪函式構成,這里我們重點介紹80位的演算法,
1.1 加解密方式
1.1.1 加密
Twine-80的加密演算法如下所示:

該演算法采用的是廣義的Feistel結構,具體結構如下圖所示:

我們可以看出,此演算法在Feistel結構的基礎上改造了位置交換的方法,我們稱之為π置換(π-1置換用于解密):

Feistel結構中S盒如下表:
void Feistel(int r,int k)
{
int i;
char a;
if(k == 1)
{
if(r != 35)
for(i = 0;i < 16;i += 2)
{
OutPut[PI[i]] = InPut[i];
a = S[InPut[i] ^ R_Key[r][i / 2]];
OutPut[PI[i + 1]] = InPut[i + 1] ^ a;
}
else
for(i = 0;i < 16;i += 2)
{
OutPut[i] = InPut[i];
a = S[InPut[i] ^ R_Key[r][i / 2]];
OutPut[i + 1] = InPut[i + 1] ^ a;
}
}
else
{
if(r != 35)
for(i = 0;i < 16;i += 2)
{
OutPut[Pi[i]] = InPut[i];
a = S[InPut[i] ^ R_Key[35 - r][i / 2]];
OutPut[Pi[i + 1]] = InPut[i + 1] ^ a;
}
else
for(i = 0;i < 16;i += 2)
{
OutPut[i] = InPut[i];
a = S[InPut[i] ^ R_Key[35 - r][i / 2]];
OutPut[i + 1] = InPut[i + 1] ^ a;
}
}
}
1.1.2 密鑰生成演算法
Twine-80的密鑰生成演算法如下所示:

方便起見,我們將演算法用圖畫出:

其中輪常數Con如下:
void MakeRKey()
{
int i,j,k;
int choose[8] = {1,3,4,6,13,14,15,16};
char ch,ConH,ConL;
char key[20] = {0};
for(i = 0;i < 10;i++)
{
ch = fgetc(KEY);
for(j = (2 * i) + 1;j >= 2 * i;j--)
{
key[j] = ch & 0x0F;
ch = ch >> 4;
}
}
for(i = 0;i < 36;i++)
{
for(j = 0;j < 8;j++)
R_Key[i][j] = key[j];
if(i < 35)
{
key[1] = key[1] ^ S[key[0]];
key[4] = key[4] ^ S[key[16]];
ConL = CON[i] & 0x07;
ConH = CON[i] >> 3;
ConH = ConH & 0x07;
key[7] = key[7] ^ ConH;
key[19] = key[19] ^ ConL;
ch = key[0];
for(j = 0;j < 19;j++)
key[j] = key[j + 1];
key[j] = ch;
for(k = 0;k < 3;k++)
{
ch = key[0];
for(j = 0;j < 18;j++)
key[j] = key[j + 1];
key[j] = ch;
}
}
}
}
1.1.3 解密
由于輪函式的等價結構,解密演算法與加密演算法除π置換與輪密鑰的注入順序不同外,其余均相似,
1.1.4 全部代碼
代碼作用是將plaintext0.txt中的資料加密為ciphertext.txt,然后再解密為plaintext.txt:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
FILE *KEY;
int flag;
int PI[16] = {5,0,1,4,7,12,3,8,13,6,9,2,15,10,11,14};
int Pi[16] = {1,2,11,6,3,0,9,4,7,10,13,14,5,8,15,12};
char S[16] = {0x0c,0x00,0x0f,0x0a,0x02,0x0b,0x09,0x05,
0x08,0x03,0x0d,0x07,0x01,0x0e,0x06,0x04};
char CON[35] = {0x01,0x02,0x04,0x08,0x10,0x20,0x03,
0x06,0x0c,0x18,0x30,0x23,0x05,0x0a,
0x14,0x28,0x13,0x26,0x0f,0x1e,0x3c,
0x3b,0x35,0x29,0x11,0x22,0x07,0x0e,
0x1c,0x38,0x33,0x25,0x09,0x12,0x24};
char InPut[16] = {0},OutPut[16] = {0};
char R_Key[36][8] = {0};
char plain[16] = {0},cipher[16] = {0};
void Read(FILE *OUT,int k)
{
int i,j;
char ch;
for(i = 0;i < 8;i++)
{
ch = fgetc(OUT);
if(ch == -1)
{
ch = 0;
flag = 0;
if(i == 0)
{
flag = -1;
return;
}
}
for(j = (2 * i) + 1;j >= 2 * i;j--)
{
if(k == 1)
plain[j] = ch & 0x0F;
else
cipher[j] = ch & 0x0F;
ch = ch >> 4;
}
}
}
void Write(FILE *IN,int k)
{
int i,j;
char ch;
for(i = 0;i < 8;i++)
{
ch = 0x00;
for(j = 2 * i;j <= (2 * i) + 1;j++)
{
ch = ch << 4;
if(k == 1)
ch = ch | cipher[j];
else
ch = ch | plain[j];
}
fputc(ch,IN);
}
}
void MakeRKey()
{
int i,j,k;
int choose[8] = {1,3,4,6,13,14,15,16};
char ch,ConH,ConL;
char key[20] = {0};
for(i = 0;i < 10;i++)
{
ch = fgetc(KEY);
for(j = (2 * i) + 1;j >= 2 * i;j--)
{
key[j] = ch & 0x0F;
ch = ch >> 4;
}
}
for(i = 0;i < 36;i++)
{
for(j = 0;j < 8;j++)
R_Key[i][j] = key[j];
if(i < 35)
{
key[1] = key[1] ^ S[key[0]];
key[4] = key[4] ^ S[key[16]];
ConL = CON[i] & 0x07;
ConH = CON[i] >> 3;
ConH = ConH & 0x07;
key[7] = key[7] ^ ConH;
key[19] = key[19] ^ ConL;
ch = key[0];
for(j = 0;j < 19;j++)
key[j] = key[j + 1];
key[j] = ch;
for(k = 0;k < 3;k++)
{
ch = key[0];
for(j = 0;j < 18;j++)
key[j] = key[j + 1];
key[j] = ch;
}
}
}
}
void Feistel(int r,int k)
{
int i;
char a;
if(k == 1)
{
if(r != 35)
for(i = 0;i < 16;i += 2)
{
OutPut[PI[i]] = InPut[i];
a = S[InPut[i] ^ R_Key[r][i / 2]];
OutPut[PI[i + 1]] = InPut[i + 1] ^ a;
}
else
for(i = 0;i < 16;i += 2)
{
OutPut[i] = InPut[i];
a = S[InPut[i] ^ R_Key[r][i / 2]];
OutPut[i + 1] = InPut[i + 1] ^ a;
}
}
else
{
if(r != 35)
for(i = 0;i < 16;i += 2)
{
OutPut[Pi[i]] = InPut[i];
a = S[InPut[i] ^ R_Key[35 - r][i / 2]];
OutPut[Pi[i + 1]] = InPut[i + 1] ^ a;
}
else
for(i = 0;i < 16;i += 2)
{
OutPut[i] = InPut[i];
a = S[InPut[i] ^ R_Key[35 - r][i / 2]];
OutPut[i + 1] = InPut[i + 1] ^ a;
}
}
}
int main()
{
int mode,i,r;
FILE *M,*C;
if((KEY = fopen("key.txt","rb")) == NULL)
{
printf("\nkey.txt Fail,Close!");
getchar();
exit(1);
}
MakeRKey();
while(1)
{
flag = 1;
printf("Plase choose:\n1. encrypt \n2. decrypt \n3. exit \n");
scanf("%d",&mode);
if(mode == 1)
{
if((M = fopen("plaintext0.txt","rb")) == NULL)
{
printf("\nplaintext.txt Fail,Close!");
getchar();
exit(1);
}
if((C = fopen("ciphertext.txt","wb")) == NULL)
{
printf("\nciphertext.txt Fail,Close!");
getchar();
exit(1);
}
while(flag)
{
Read(M,1);
if(flag == -1)
break;
for(i = 0;i < 16;i++)
InPut[i] = plain[i];
for(r = 0;r < 36;r++)
{
Feistel(r,1);
for(i = 0;i < 16;i++)
InPut[i] = OutPut[i];
}
for(i = 0;i < 16;i++)
cipher[i] = OutPut[i];
Write(C,1);
}
fclose(M);
fclose(C);
}
if(mode == 2)
{
if((C = fopen("ciphertext.txt","rb")) == NULL)
{
printf("\nciphertext.txt Fail,Close!");
getchar();
exit(1);
}
if((M = fopen("plaintext.txt","wb")) == NULL)
{
printf("\nplaintext.txt Fail,Close!");
getchar();
exit(1);
}
while(flag)
{
Read(C,2);
if(flag == -1)
break;
for(i = 0;i < 16;i++)
InPut[i] = cipher[i];
for(r = 0;r < 36;r++)
{
Feistel(r,2);
for(i = 0;i < 16;i++)
InPut[i] = OutPut[i];
}
for(i = 0;i < 16;i++)
plain[i] = OutPut[i];
Write(M,2);
}
fclose(M);
fclose(C);
}
if(mode == 3)
{
fclose(KEY);
exit(0);
}
system("pause");
system("cls");
}
return 0;
}
1.2. 分組密碼的模式
在陣列密碼中,如何將長的明文資料分成演算法要求的長度也是一個問題,為此,人們提出了分組密碼的分組模式:
1.2.1 ECB模式
加密:

解密:

1.2.2 CBC模式
加密:

解密:

1.2.3 CFB模式
加密:

解密:

1.2.4 OFB模式
加密:

解密:

1.2.5 CTR模式
加密:

解密:

2.序列密碼
序列密碼也稱為流密碼(Stream Cipher),它是對稱密碼演算法的一種,序列密碼具有實作簡單、便于硬體實施、加解密處理速度快、沒有或只有有限的錯誤傳播等特點,因此在實際應用中,特別是專用或機密機構中保持著優勢,典型的應用領域包括無線通信、外交通信,
1949年Shannon證明了只有一次一密的密碼體制是絕對安全的,這給序列密碼技術的研究以強大的支持,序列密碼方案的發展是模仿一次一密系統的嘗試,或者說“一次一密”的密碼方案是序列密碼的雛形,如果序列密碼所使用的是真正隨機方式的、與訊息流長度相同的密鑰流,則此時的序列密碼就是一次一密的密碼體制,若能以一種方式產生一隨機序列(密鑰流),這一序列由密鑰所確定,則利用這樣的序列就可以進行加密,即將密鑰、明文表示成連續的符號或二進制,對應地進行加密,加解密時一次處理明文中的一個或幾個位元,
在序列密碼中,密鑰流由密鑰流發生器f產生:zi=f(k,si),這里的si是加密器中存盤器(記憶元件)在i時刻的狀態,根據加密器中的記憶元件si的存貯狀態是否依賴于明文字符,序列密碼可進一步分成同步和自同步兩種,如果si獨立于明文字符則稱為同步流密碼,否則稱為自同步流密碼,
序列密碼演算法主要依靠(線性)反饋移位暫存器,這里就不過多說明了,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/282567.html
標籤:其他
