📄 des.c
字号:
/*#ifndef __WIN95__#include <windef.h>#else#include <basedef.h>#endif*/#include "bc_des.h"#include "des_tbl.h"// DES ECB encryption codeextern DWORD SP_boxes[8][64];extern DWORD KeyPerm[8][64];/* Macroses to transform array of 4 bytes to 32-bit dwords * (and reverse) without depending on the Little-Endian or * Big-Endian processor's architecture */#define BYTES_TO_DWORD(b,d) (d = ((DWORD)(*((b)++))), \ d |= ((DWORD)(*((b)++)))<< 8, \ d |= ((DWORD)(*((b)++)))<<16, \ d |= ((DWORD)(*((b)++)))<<24)#define DWORD_TO_4BYTES(d,b) (*((b)++)=(BYTE)(((d) )&0xff), \ *((b)++)=(BYTE)(((d)>> 8)&0xff), \ *((b)++)=(BYTE)(((d)>>16)&0xff), \ *((b)++)=(BYTE)(((d)>>24)&0xff))/* First of all, take into accounts the bytes and bites ordering used in DES: DES: 1 2 3 4 5 6 7 8 .... 57 58 59 60 61 62 63 64 INTEL: 63 62 61 60 59 58 57 56 .... 7 6 5 4 3 2 1 0 According to the DES, every 8-th bits is not used: for DES the bites 8, 16, 32, ..., 64 are excluded, for INTEL: 56, 48, 40, ..., 0 are excluded According to the above rool of numbering, the tables used in DES (for Initial Permutation, Final Permutation, Key Permutation, Compression Permutation, Expansion Permutation and P-Box permutation) have to be re-written.*//* Some main ideas used to optimize DES software implementation: a). Do not make an Expansion Permutation of 32-bit to 48 bit (32-bit of data - right half of 64-bit of data), but make a correspondent preparation of the Key. So, the step of Expansion Permutation and XORing 48 bit of Expanded data and 48 bit of Compressed key will be replaced by 2 XOR operations: 32 bit of data XOR first 32 bit part of prepeared key, then, the same 32 bit of data XOR second 32-bit part of prepeared key b). Combine S-Box Substitution and P-Box Permutation operations. c). For the best performance 56-bit encryption key have to be extendended to 128-byte array, i.e. for each of 16 rounds of DES we prepare a unique pair of two 32-bit (4-bytes) words (see 'a)' above). d). We can use XOR, SHIFT, AND operations to swap bits between words. For example, we have: word A word B 0 1 2 3 4 5 6 7 We want to get: word A word B 0 4 2 6 1 5 3 7First, shift word A to get bites 1, 3 on the "right place" word TMP = (word A) >> 1 = 1 2 3 - TMP = TMP ^ B = 1^4 2^5 3^6 7 we don't want to change bits 5 and 7 in the B word, so TMP = TMP & MASK = TMP & 1010 = 1^4 - 3^6 - now we can easy get the word B: B = B ^ TMP = (4 5 6 7) ^ (1^4 - 3^6 -) = 1 5 3 7 if we shift our "masking" TMP word reverse - we get a mask for A word: TMP = TMP << 1 = - 1^4 - 3^6 now we can easy get the word A: A = A ^ TMP = (0 1 2 3) ^ (- 1^4 - 3^6) = 0 4 2 6 The example above may be used to swap not only single bits, but also bit sequencies. In this case you should use shift on the value, equal to the number of bits in pattern. As you see, all this opearations may be written like: TMP = ((A >> size) ^ B) & mask; B ^ = TMP; A ^= TMP << size;*/#define PERMUTATION(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),\ (b)^=(t),\ (a)^=((t)<<(n)))#define HPERMUTATION(a,t,n,m) ((t)=((((a)<<(16-(n)))^(a))&(m)),\ (a)=(a)^(t)^(t>>(16-(n))))void DES_PrepareKeySchedule( BYTE *InKey, /* 8-bytes array of key */ DWORD *OutKeySchedule ) /* [16][2] array of DWORDs */ { static DWORD dwLow, dwHig, dwTmpA, dwTmpB, *dwKS; static BYTE *bTmp; static int i; static char shifts2[16]={0,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0}; bTmp = InKey; dwKS = OutKeySchedule; BYTES_TO_DWORD( bTmp, dwLow); BYTES_TO_DWORD( bTmp, dwHig); PERMUTATION (dwHig, dwLow, dwTmpA, 4,0x0f0f0f0f); HPERMUTATION(dwLow, dwTmpA,-2,0xcccc0000); HPERMUTATION(dwHig, dwTmpA,-2,0xcccc0000); PERMUTATION (dwHig, dwLow, dwTmpA, 1,0x55555555); PERMUTATION (dwLow, dwHig, dwTmpA, 8,0x00ff00ff); PERMUTATION (dwHig, dwLow, dwTmpA, 1,0x55555555); dwHig = (((dwHig & 0x000000ff)<<16) | (dwHig & 0x0000ff00) | ((dwHig & 0x00ff0000)>>16) | ((dwLow & 0xf0000000)>>4)); dwLow &= 0x0fffffff; for (i=0; i<16; i++) { if (shifts2[i]) { dwLow = ((dwLow>>2) | (dwLow<<26)); dwHig = ((dwHig>>2) | (dwHig<<26)); } else { dwLow = ((dwLow>>1) | (dwLow<<27)); dwHig = ((dwHig>>1) | (dwHig<<27)); } dwLow &= 0x0fffffff; dwHig &= 0x0fffffff; dwTmpB = KeyPerm[0][ (dwLow )&0x3f ]| KeyPerm[1][((dwLow>> 6)&0x03) | ((dwLow>> 7)&0x3c)]| KeyPerm[2][((dwLow>>13)&0x0f) | ((dwLow>>14)&0x30)]| KeyPerm[3][((dwLow>>20)&0x01) | ((dwLow>>21)&0x06) | ((dwLow>>22)&0x38)]; dwTmpA = KeyPerm[4][ (dwHig )&0x3f ]| KeyPerm[5][((dwHig>> 7)&0x03) | ((dwHig>> 8)&0x3c)]| KeyPerm[6][ (dwHig>>15)&0x3f ]| KeyPerm[7][((dwHig>>21)&0x0f) | ((dwHig>>22)&0x30)]; /* table contains 0213 4657 */ *(dwKS++) = ((dwTmpA << 16) | (dwTmpB & 0x0000ffff)) &0xffffffff; dwTmpB = ((dwTmpB >> 16) | (dwTmpA & 0xffff0000)); dwTmpB = (dwTmpB << 4) | (dwTmpB >> 28); *(dwKS++) = dwTmpB & 0xffffffff; }}#define D_ENCRYPT(Left, Right, Ks, Num, TmpA, TmpB ) \ TmpA = (Right ^ Ks[Num ]); \ TmpB = (Right ^ Ks[Num+1]); \ TmpB = ((TmpB >> 4) + (TmpB << 28)); \ Left ^= SP_boxes[1][(TmpB )&0x3f]| \ SP_boxes[3][(TmpB>> 8)&0x3f]| \ SP_boxes[5][(TmpB>>16)&0x3f]| \ SP_boxes[7][(TmpB>>24)&0x3f]| \ SP_boxes[0][(TmpA )&0x3f]| \ SP_boxes[2][(TmpA>> 8)&0x3f]| \ SP_boxes[4][(TmpA>>16)&0x3f]| \ SP_boxes[6][(TmpA>>24)&0x3f];void DES_ECB_mode( BYTE *Input, /* 8 bytes of input data */ BYTE *Output, /* 8 bytes of output data */ DWORD *KeySchedule, /* [16][2] array of DWORDs */ BYTE Operation) /* DES_ECB_ENCRYPT or DES_ECB_DECRYPT */{ static BYTE *bInp, *bOut; static DWORD dwLeft, dwRigh, dwTmp, dwTmp1; bInp = Input; bOut = Output; BYTES_TO_DWORD( bInp, dwLeft ); BYTES_TO_DWORD( bInp, dwRigh ); /* Initial Permutation */ PERMUTATION(dwRigh, dwLeft, dwTmp, 4, 0x0f0f0f0f); PERMUTATION(dwLeft, dwRigh, dwTmp,16, 0x0000ffff); PERMUTATION(dwRigh, dwLeft, dwTmp, 2, 0x33333333); PERMUTATION(dwLeft, dwRigh, dwTmp, 8, 0x00ff00ff); PERMUTATION(dwRigh, dwLeft, dwTmp, 1, 0x55555555); /* dwRigh and dwLeft has reversed bit orders - itwill be taken into account in the next step */ /* The initial rotate is done outside the loop. This required the * SP_boxes values to be rotated 1 bit to the right. */ dwTmp = (dwRigh<<1) | (dwRigh>>31); dwRigh = (dwLeft<<1) | (dwLeft>>31); dwLeft = dwTmp; /* clear the top bits on machines with 8byte longs */ dwLeft &= 0xffffffff; dwRigh &= 0xffffffff; if (Operation == DES_ECB_ENCRYPT) { /* Key order */ D_ENCRYPT(dwLeft, dwRigh, KeySchedule, 0, dwTmp, dwTmp1); /* 1 */ D_ENCRYPT(dwRigh, dwLeft, KeySchedule, 2, dwTmp, dwTmp1); /* 2 */ D_ENCRYPT(dwLeft, dwRigh, KeySchedule, 4, dwTmp, dwTmp1); /* 3 */ D_ENCRYPT(dwRigh, dwLeft, KeySchedule, 6, dwTmp, dwTmp1); /* 4 */ D_ENCRYPT(dwLeft, dwRigh, KeySchedule, 8, dwTmp, dwTmp1); /* 5 */ D_ENCRYPT(dwRigh, dwLeft, KeySchedule, 10, dwTmp, dwTmp1); /* 6 */ D_ENCRYPT(dwLeft, dwRigh, KeySchedule, 12, dwTmp, dwTmp1); /* 7 */ D_ENCRYPT(dwRigh, dwLeft, KeySchedule, 14, dwTmp, dwTmp1); /* 8 */ D_ENCRYPT(dwLeft, dwRigh, KeySchedule, 16, dwTmp, dwTmp1); /* 9 */ D_ENCRYPT(dwRigh, dwLeft, KeySchedule, 18, dwTmp, dwTmp1); /* 10 */ D_ENCRYPT(dwLeft, dwRigh, KeySchedule, 20, dwTmp, dwTmp1); /* 11 */ D_ENCRYPT(dwRigh, dwLeft, KeySchedule, 22, dwTmp, dwTmp1); /* 12 */ D_ENCRYPT(dwLeft, dwRigh, KeySchedule, 24, dwTmp, dwTmp1); /* 13 */ D_ENCRYPT(dwRigh, dwLeft, KeySchedule, 26, dwTmp, dwTmp1); /* 14 */ D_ENCRYPT(dwLeft, dwRigh, KeySchedule, 28, dwTmp, dwTmp1); /* 15 */ D_ENCRYPT(dwRigh, dwLeft, KeySchedule, 30, dwTmp, dwTmp1); /* 16 */ } else { D_ENCRYPT(dwLeft, dwRigh, KeySchedule, 30, dwTmp, dwTmp1); /* 16 */ D_ENCRYPT(dwRigh, dwLeft, KeySchedule, 28, dwTmp, dwTmp1); /* 15 */ D_ENCRYPT(dwLeft, dwRigh, KeySchedule, 26, dwTmp, dwTmp1); /* 14 */ D_ENCRYPT(dwRigh, dwLeft, KeySchedule, 24, dwTmp, dwTmp1); /* 13 */ D_ENCRYPT(dwLeft, dwRigh, KeySchedule, 22, dwTmp, dwTmp1); /* 12 */ D_ENCRYPT(dwRigh, dwLeft, KeySchedule, 20, dwTmp, dwTmp1); /* 11 */ D_ENCRYPT(dwLeft, dwRigh, KeySchedule, 18, dwTmp, dwTmp1); /* 10 */ D_ENCRYPT(dwRigh, dwLeft, KeySchedule, 16, dwTmp, dwTmp1); /* 9 */ D_ENCRYPT(dwLeft, dwRigh, KeySchedule, 14, dwTmp, dwTmp1); /* 8 */ D_ENCRYPT(dwRigh, dwLeft, KeySchedule, 12, dwTmp, dwTmp1); /* 7 */ D_ENCRYPT(dwLeft, dwRigh, KeySchedule, 10, dwTmp, dwTmp1); /* 6 */ D_ENCRYPT(dwRigh, dwLeft, KeySchedule, 8, dwTmp, dwTmp1); /* 5 */ D_ENCRYPT(dwLeft, dwRigh, KeySchedule, 6, dwTmp, dwTmp1); /* 4 */ D_ENCRYPT(dwRigh, dwLeft, KeySchedule, 4, dwTmp, dwTmp1); /* 3 */ D_ENCRYPT(dwLeft, dwRigh, KeySchedule, 2, dwTmp, dwTmp1); /* 2 */ D_ENCRYPT(dwRigh, dwLeft, KeySchedule, 0, dwTmp, dwTmp1); /* 1 */ } dwLeft = (dwLeft>>1) | (dwLeft<<31); dwRigh = (dwRigh>>1) | (dwRigh<<31); /* clear the top bits on machines with 8byte longs */ dwLeft &= 0xffffffff; dwRigh &= 0xffffffff; /* Do we need to swap dwLeft and dwRigh? * We have not to do the swap * (We remember they are reversed) * So - all we have to do is to make a correspondent Final Permutation */ PERMUTATION(dwRigh, dwLeft, dwTmp, 1,0x55555555); PERMUTATION(dwLeft, dwRigh, dwTmp, 8,0x00ff00ff); PERMUTATION(dwRigh, dwLeft, dwTmp, 2,0x33333333); PERMUTATION(dwLeft, dwRigh, dwTmp,16,0x0000ffff); PERMUTATION(dwRigh, dwLeft, dwTmp, 4,0x0f0f0f0f); /* Place our two 32-bits results into 8 bytes of output data */ DWORD_TO_4BYTES( dwLeft, bOut ); DWORD_TO_4BYTES( dwRigh, bOut );}//************ DES CBC mode encryption **************VOIDEncrypt( DWORD *IVector, DWORD *KeyAddress, DWORD *SrcBuffer, DWORD *DstBuffer, DWORD Length ) // in bytes{ DWORD i; DWORD buffer[2]; buffer[0] = IVector[0]; buffer[1] = IVector[1]; for(i = 0; i < (Length >> 2); i = i+2) { // do EBC encryption of (Initial_Vector XOR Data) buffer[0] ^= SrcBuffer[i]; buffer[1] ^= SrcBuffer[i+1]; DES_ECB_mode( (BYTE *)buffer, (BYTE *)buffer, KeyAddress, DES_ECB_ENCRYPT ); DstBuffer[i] = buffer[0]; DstBuffer[i+1] = buffer[1]; }}//************ DES CBC mode decryption **************VOIDDecrypt( DWORD *IVector, DWORD *KeyAddress, DWORD *SrcBuffer, DWORD *DstBuffer, DWORD Length ) // in bytes{ DWORD i; DWORD buffer[2], ivectorL, ivectorR, oldSrcL, oldSrcR; ivectorL = IVector[0]; ivectorR = IVector[1]; for(i = 0; i < (Length >> 2); i = i+2) { buffer[0] = oldSrcL = SrcBuffer[i]; buffer[1] = oldSrcR = SrcBuffer[i+1]; // Encrypted Data -> new IV, // then do EBC decryption of Encrypted Data, // then XOR decrypted data with old IV DES_ECB_mode( (BYTE *)buffer, (BYTE *)buffer, KeyAddress, DES_ECB_DECRYPT ); DstBuffer[i] = buffer[0] ^ ivectorL; DstBuffer[i+1] = buffer[1] ^ ivectorR; ivectorL = oldSrcL; ivectorR = oldSrcR; }}//*********** DES Key Extension **************BOOLKeyExtend( PUCHAR KeySource, // 32 8-bit uchars PDWORD KeyDestination ) // (128/4) 32-bit dwords{ DES_PrepareKeySchedule( KeySource, KeyDestination ); return TRUE;}char des_c[]="$Id: des.c,v 1.3 2002/10/29 07:11:46 crypt Rel-1.6-3 $";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -