分组加密算法在加解密中十分常见,因其安全性高,计算速度快。常用的有DES、AES、IDEA和RC6等 。
由于DES的安全性存在争议,且56位的密钥太短(1997年RSA悬赏破解),现在使用的是3DES和AES(高级加密标准)。
下面说一说DES,数据加密标准(DES)是一个分组加密算法,也是对称加密算法,加解密的密钥一样。
DES采用Feistel结构设计,处理的明文分组为64位,有效密钥为56位,输出密文为64位,是具有16轮迭代的分组对称密码算法。
DES算法
- /*
- DES算法,明文分组为64位(不足64位时补0),有效密钥56位,输出密文64位,16轮迭代
- 由于没有保存长度信息,对于可能有填充部分,最后解密的明文最后一块可能会出现多余字符
- 本程序的位从右往左为0~63()
- */
- #include<stdio.h>
- #include<stdlib.h>
- #include<string.h>
- unsigned char IP[64+1] = {
- 58,50,42,34,26,18,10,2,
- 60,52,44,36,28,20,12,4,
- 62,54,46,38,30,22,14,6,
- 64,56,48,40,32,24,16,8,
- 57,49,41,33,25,17,9,1,
- 59,51,43,35,27,19,11,3,
- 61,53,45,37,29,21,13,5,
- 63,55,47,39,31,23,15,7,0};
- unsigned char IPRev[64+1] = {
- 40,8,48,16,56,24,64,32,
- 39,7,47,15,55,23,63,31,
- 38,6,46,14,54,22,62,30,
- 37,5,45,13,53,21,61,29,
- 36,4,44,12,52,20,60,28,
- 35,3,43,11,51,19,59,27,
- 34,2,42,10,50,18,58,26,
- 33,1,41,9,49,17,57,25,0};
- unsigned char EExt[48+1] = {
- 32,1,2,3,4,5,
- 4,5,6,7,8,9,
- 8,9,10,11,12,13,
- 12,13,14,15,16,17,
- 16,17,18,19,20,21,
- 20,21,22,23,24,25,
- 24,25,26,27,28,29,
- 28,29,30,31,32,1,0};
- unsigned char S[8][64] ={
- {14,4,13,1,2,15,11,8,3,10,6,12,5,9,0,7,
- 0,15,7,4,14,2,13,1,10,6,12,11,9,5,3,8,
- 4,1,14,8,13,6,2,11,15,12,9,7,3,10,5,0,
- 15,12,8,2,4,9,1,7,5,11,3,14,10,0,6,13},{
- 15,1,8,14,6,11,3,4,9,7,2,13,12,0,5,10,
- 3,13,4,7,15,2,8,14,12,0,1,10,6,9,11,5,
- 0,14,7,11,10,4,13,1,5,8,12,6,9,3,2,15,
- 13,8,10,1,3,15,4,2,11,6,7,12,0,5,14,9},{
- 10,0,9,14,6,3,15,5,1,13,12,7,11,4,2,8,
- 13,7,0,9,3,4,6,10,2,8,5,14,12,11,15,1,
- 13,6,4,9,8,15,3,0,11,1,2,12,5,10,14,7,
- 1,10,13,0,6,9,8,7,4,15,14,3,11,5,2,12},{
- 7,13,14,3,0,6,9,10,1,2,8,5,11,12,4,15,
- 13,8,11,5,6,15,0,3,4,7,2,12,1,10,14,9,
- 10,6,9,0,12,11,7,13,15,1,3,14,5,2,8,4,
- 3,15,0,6,10,1,13,8,9,4,5,11,12,7,2,14},{
- 2,12,4,1,7,10,11,6,8,5,3,15,13,0,14,9,
- 14,11,2,12,4,7,13,1,5,0,15,10,3,9,8,6,
- 4,2,1,11,10,13,7,8,15,9,12,5,6,3,0,14,
- 11,8,12,7,1,14,2,13,6,15,0,9,10,4,5,3},{
- 12,1,10,15,9,2,6,8,0,13,3,4,14,7,5,11,
- 10,15,4,2,7,12,9,5,6,1,13,14,0,11,3,8,
- 9,14,15,5,2,8,12,3,7,0,4,10,1,13,11,6,
- 4,3,2,12,9,5,15,10,11,14,1,7,6,0,8,13},{
- 4,11,2,14,15,0,8,13,3,12,9,7,5,10,6,1,
- 13,0,11,7,4,9,1,10,14,3,5,12,2,15,8,6,
- 1,4,11,13,12,3,7,14,10,15,6,8,0,5,9,2,
- 6,11,13,8,1,4,10,7,9,5,0,15,14,2,3,12},{
- 13,2,8,4,6,15,11,1,10,9,3,14,5,0,12,7,
- 1,15,13,8,10,3,7,4,12,5,6,11,0,14,9,2,
- 7,11,4,1,9,12,14,2,0,6,10,13,15,3,5,8,
- 2,1,14,7,4,10,8,13,15,12,9,0,3,5,6,11}};
- unsigned char P[56+1] = {
- 16,7,20,21,29,12,28,17,
- 1,15,23,26,5,18,31,10,
- 2,8,24,14,32,27,3,9,
- 19,13,30,6,22,11,4,25,0};
- unsigned char PC1[56+1] = {
- 57,49,41,33,25,17,9,
- 1,58,50,42,34,26,18,
- 10,2,59,51,43,35,27,
- 19,11,3,60,52,44,36,
- 63,55,47,39,31,23,15,
- 7,62,54,46,38,30,22,
- 14,6,61,53,45,37,29,
- 21,13,5,28,20,12,4,0};
- unsigned char PC2[48+1] = {
- 57,49,41,33,25,17,9,1,
- 58,50,42,34,26,18,10,2,
- 59,51,43,35,27,19,11,3,
- 60,52,44,36,63,55,47,39,
- 31,23,15,7,62,54,46,38,
- 30,22,14,6,61,53,45,37,0};
- unsigned char LS[16] = {
- 1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1};
- FILE *fp;
- unsigned long long Message;
- int flag;
- unsigned long long keys[16];
- void getMessage(char mode);
- unsigned long long Rep(unsigned char rp[],unsigned long long s);//置换
- unsigned int SBoxC(unsigned long long x);
- void GenKeys(char mode);
- unsigned int L,R;
- unsigned long long K;
- int main(int argc, char *argv[])
- {
- char mode;
- char filename[256];
- unsigned char key[10];
- mode = *argv[1];
- strcpy(filename,argv[2]);
- if(argc != 4)
- {
- printf("参数有错误!\n");
- exit(0);
- }
- if(strlen(argv[3])!=8)
- {
- printf("密钥长度不正确!");
- exit(0);
- }
- strcpy(key,argv[3]);
- /* printf("请选择操作方式:加密 e ,解密 d : ");
- scanf("%c",&mode);
- printf("请输入文件名:");
- scanf("%s",filename);
- printf("请输入密钥(64bit):");
- scanf("%s",key); */
- // printf("%s",filename);
- // system("pause");
- if((fp=fopen(filename,"rb")) == NULL)
- {
- printf("文件无法打开");
- exit(0);
- }
- int inc = 0;
- K = 0;
- for(inc = 0 ;inc < 8; inc++)
- K |= (((unsigned long long)key[inc])<<((7-inc)<<3));
- #ifdef DEBUG
- printf(" K %016llx ",K);
- #endif
- FILE *fpOut;
- char fileOut[200];
- if(mode == 'e')
- strcat(strcpy(fileOut,"ED\0"),filename);
- else
- strcat(strcpy(fileOut,"DD\0"),filename+2);
- fpOut= fopen(fileOut,"wb");
- // fseek(fp, 0, SEEK_END);
- // fgetpos(fp, &pos);
- flag = 1;//判断是否结束
- int T;
- GenKeys(mode);
- getMessage(mode);
- while(flag)
- {
- Message = Rep(IP,Message);
- L = Message>>32;
- R = Message;
- int i =0;
- for(i =0 ; i < 16; i++)
- {
- T = R;
- R = Rep(P,SBoxC(Rep(EExt,(unsigned long long)R)^keys[i]))^L;
- L = T;
- }
- Message = (((unsigned long long)R)<<32)|L;
- Message = Rep(IPRev,Message);
- if(mode == 'e')
- fwrite(&Message,1,8,fpOut);
- else
- {
- Message = (Message>>56)|((Message&0x00ff000000000000)>>40)|((Message&0x0000ff0000000000)>>24)|((Message&0x000000ff00000000)>>8)|
- (Message<<56)|((Message&0x000000000000ff00)<<40)|((Message&0x0000000000ff0000)<<24)|((Message&0x00000000ff000000)<<8);
- fwrite(&Message,1,8,fpOut);
- }
- /* for(i = 0 ; i < 8 ; i++)
- {
- int out =(Message&(0x00000000000000ff<<(i*8))>>(i*8));
- fwrite(&out,1,1,fpOut);
- } */
- getMessage(mode);
- }
- fclose(fp);
- fclose(fpOut);
- return 0;
- }
- void getMessage(char mode)
- {
- Message = 0;
- flag = fread((void *)&Message,1,8,fp);
- // printf(" flag = %d %d %d ",flag,feof(fp),ferror(fp));
- if(flag == 0)
- {
- return;
- }
- #ifdef DEBUG
- printf("Mm %016llx ",Message);
- #endif
- if(mode == 'e')
- Message = (Message>>56)|((Message&0x00ff000000000000)>>40)|((Message&0x0000ff0000000000)>>24)|((Message&0x000000ff00000000)>>8)|
- (Message<<56)|((Message&0x000000000000ff00)<<40)|((Message&0x0000000000ff0000)<<24)|((Message&0x00000000ff000000)<<8);
- #ifdef DEBUG
- printf("Mess %016llx ",Message);
- // system("pause");
- #endif
- }
- unsigned long long Rep(unsigned char rp[],unsigned long long s)//置换
- {
- #ifdef DEBUG
- printf("in Rep ");
- #endif
- int i = 0;
- unsigned long long ans=0;
- unsigned long long con = 1;
- for(i = 0 ; i < strlen(rp); i++)
- {
- ans |= ((s&(con << (rp[i]-1)))>> (rp[i]-1))<<i;
- #ifdef DEBUG
- printf("time= %d ans %016llx ",i,ans);
- #endif
- // system("pause");
- }
- #ifdef DEBUG
- printf(" Rep end ");
- #endif
- return ans;
- }
- unsigned int SBoxC(unsigned long long x)
- {
- #ifdef DEBUG
- printf("in Sbox ");
- #endif
- int i = 0 , ans = 0;
- unsigned long long con = 0x3f;
- int t1_6 = 0,tr=0,tc=0;
- for(i = 0; i < 8; i++ )
- {
- #ifdef DEBUG
- printf(" Sbox For Begin ");
- #endif
- t1_6 = (x & (con <<(i*6)))>>(i*6);
- tr = ((t1_6&(1<<5))>>4)|(t1_6&1);
- tc = (t1_6&0x1f)>>1;
- ans|=(S[7-i][(tr<<4)+tc])<<(i*4);
- #ifdef DEBUG
- printf(" ii = %d %x ",i,ans);
- system("pause");
- printf(" Sbox For end ");
- #endif
- }
- #ifdef DEBUG
- printf(" Sbox end ");
- #endif
- return ans;
- }
- unsigned int C,D;
- void GenKeys(char mode)
- {
- unsigned long long con = 0x0fffffff;
- K = Rep(PC1,K);
- C = (K&(con<<28))>>28;
- D = K&con;
- int i;
- if(mode == 'e')
- {
- for(i = 0; i < 16; i++)
- {
- C = (C<<LS[i])|(C>>(32-LS[i]));
- D = (D<<LS[i])|(D>>(32-LS[i]));
- K = (C<<28)|D;
- keys[i] = Rep(PC2,K);
- }
- }
- else
- {
- for(i = 0; i < 16; i++)
- {
- C = (C<<LS[i])|(C>>(32-LS[i]));
- D = (D<<LS[i])|(D>>(32-LS[i]));
- K = (C<<28)|D;
- keys[15 - i] = Rep(PC2,K);
- }
- }
- }
编译器使用的是MingwGcc编译器。