des.c
来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 684 行 · 第 1/2 页
C
684 行
/* * The PC-1 Permutation * If we number the bits of the 8 bytes of key input like this (in octal): * 00 01 02 03 04 05 06 07 * 10 11 12 13 14 15 16 17 * 20 21 22 23 24 25 26 27 * 30 31 32 33 34 35 36 37 * 40 41 42 43 44 45 46 47 * 50 51 52 53 54 55 56 57 * 60 61 62 63 64 65 66 67 * 70 71 72 73 74 75 76 77 * then after the PC-1 permutation, * C0 is * 70 60 50 40 30 20 10 00 * 71 61 51 41 31 21 11 01 * 72 62 52 42 32 22 12 02 * 73 63 53 43 * D0 is * 76 66 56 46 36 26 16 06 * 75 65 55 45 35 25 15 05 * 74 64 54 44 34 24 14 04 * 33 23 13 03 * and these parity bits have been discarded: * 77 67 57 47 37 27 17 07 * * We achieve this by flipping the input matrix about the diagonal from 70-07, * getting left = * 77 67 57 47 37 27 17 07 (these are the parity bits) * 76 66 56 46 36 26 16 06 * 75 65 55 45 35 25 15 05 * 74 64 54 44 34 24 14 04 * right = * 73 63 53 43 33 23 13 03 * 72 62 52 42 32 22 12 02 * 71 61 51 41 31 21 11 01 * 70 60 50 40 30 20 10 00 * then byte swap right, ala htonl() on a little endian machine. * right = * 70 60 50 40 30 20 10 00 * 71 67 57 47 37 27 11 07 * 72 62 52 42 32 22 12 02 * 73 63 53 43 33 23 13 03 * then * c0 = right >> 4; * d0 = ((left & 0x00ffffff) << 4) | (right & 0xf);*/#define FLIP_RIGHT_DIAGONAL(word, temp) \ temp = (word ^ (word >> 18)) & 0x00003333; \ word ^= temp | (temp << 18); \ temp = (word ^ (word >> 9)) & 0x00550055; \ word ^= temp | (temp << 9);#define BYTESWAP(word, temp) \ word = (word >> 16) | (word << 16); \ temp = 0x00ff00ff; \ word = ((word & temp) << 8) | ((word >> 8) & temp); #define PC1(left, right, c0, d0, temp) \ right ^= temp = ((left >> 4) ^ right) & 0x0f0f0f0f; \ left ^= temp << 4; \ FLIP_RIGHT_DIAGONAL(left, temp); \ FLIP_RIGHT_DIAGONAL(right, temp); \ BYTESWAP(right, temp); \ c0 = right >> 4; \ d0 = ((left & 0x00ffffff) << 4) | (right & 0xf); #define LEFT_SHIFT_1( reg ) (((reg << 1) | (reg >> 27)) & 0x0FFFFFFF)#define LEFT_SHIFT_2( reg ) (((reg << 2) | (reg >> 26)) & 0x0FFFFFFF)/* * setup key schedules from key */void DES_MakeSchedule( HALF * ks, BYTE * key, DESDirection direction){ register HALF left, right; register HALF c0, d0; register HALF temp; int delta; unsigned int ls;#if defined(_X86_) left = HALFPTR(key)[0]; right = HALFPTR(key)[1]; BYTESWAP(left, temp); BYTESWAP(right, temp);#else if (((ptrdiff_t)key & 0x03) == 0) { left = HALFPTR(key)[0]; right = HALFPTR(key)[1]; #if defined(IS_LITTLE_ENDIAN) BYTESWAP(left, temp); BYTESWAP(right, temp);#endif } else { left = ((HALF)key[0] << 24) | ((HALF)key[1] << 16) | ((HALF)key[2] << 8) | key[3]; right = ((HALF)key[4] << 24) | ((HALF)key[5] << 16) | ((HALF)key[6] << 8) | key[7]; }#endif PC1(left, right, c0, d0, temp); if (direction == DES_ENCRYPT) { delta = 2 * (int)sizeof(HALF); } else { ks += 30; delta = (-2) * (int)sizeof(HALF); } for (ls = 0x8103; ls; ls >>= 1) { if ( ls & 1 ) { c0 = LEFT_SHIFT_1( c0 ); d0 = LEFT_SHIFT_1( d0 ); } else { c0 = LEFT_SHIFT_2( c0 ); d0 = LEFT_SHIFT_2( d0 ); }#ifdef USE_INDEXING#define PC2LOOKUP(b,c) PC2[b][c] left = PC2LOOKUP(0, ((c0 >> 22) & 0x3F) ); left |= PC2LOOKUP(1, ((c0 >> 13) & 0x3F) ); left |= PC2LOOKUP(2, ((c0 >> 4) & 0x38) | (c0 & 0x7) ); left |= PC2LOOKUP(3, ((c0>>18)&0xC) | ((c0>>11)&0x3) | (c0&0x30)); right = PC2LOOKUP(4, ((d0 >> 22) & 0x3F) ); right |= PC2LOOKUP(5, ((d0 >> 15) & 0x30) | ((d0 >> 14) & 0xf) ); right |= PC2LOOKUP(6, ((d0 >> 7) & 0x3F) ); right |= PC2LOOKUP(7, ((d0 >> 1) & 0x3C) | (d0 & 0x3));#else#define PC2LOOKUP(b,c) *(HALF *)((BYTE *)&PC2[b][0]+(c)) left = PC2LOOKUP(0, ((c0 >> 20) & 0xFC) ); left |= PC2LOOKUP(1, ((c0 >> 11) & 0xFC) ); left |= PC2LOOKUP(2, ((c0 >> 2) & 0xE0) | ((c0 << 2) & 0x1C) ); left |= PC2LOOKUP(3, ((c0>>16)&0x30)|((c0>>9)&0xC)|((c0<<2)&0xC0)); right = PC2LOOKUP(4, ((d0 >> 20) & 0xFC) ); right |= PC2LOOKUP(5, ((d0 >> 13) & 0xC0) | ((d0 >> 12) & 0x3C) ); right |= PC2LOOKUP(6, ((d0 >> 5) & 0xFC) ); right |= PC2LOOKUP(7, ((d0 << 1) & 0xF0) | ((d0 << 2) & 0x0C));#endif /* left contains key bits for S1 S3 S2 S4 */ /* right contains key bits for S6 S8 S5 S7 */ temp = (left << 16) /* S2 S4 XX XX */ | (right >> 16); /* XX XX S6 S8 */ ks[0] = temp; temp = (left & 0xffff0000) /* S1 S3 XX XX */ | (right & 0x0000ffff);/* XX XX S5 S7 */ ks[1] = temp; ks = (HALF*)((BYTE *)ks + delta); }}/* * The DES Initial Permutation * if we number the bits of the 8 bytes of input like this (in octal): * 00 01 02 03 04 05 06 07 * 10 11 12 13 14 15 16 17 * 20 21 22 23 24 25 26 27 * 30 31 32 33 34 35 36 37 * 40 41 42 43 44 45 46 47 * 50 51 52 53 54 55 56 57 * 60 61 62 63 64 65 66 67 * 70 71 72 73 74 75 76 77 * then after the initial permutation, they will be in this order. * 71 61 51 41 31 21 11 01 * 73 63 53 43 33 23 13 03 * 75 65 55 45 35 25 15 05 * 77 67 57 47 37 27 17 07 * 70 60 50 40 30 20 10 00 * 72 62 52 42 32 22 12 02 * 74 64 54 44 34 24 14 04 * 76 66 56 46 36 26 16 06 * * One way to do this is in two steps: * 1. Flip this matrix about the diagonal from 70-07 as done for PC1. * 2. Rearrange the bytes (rows in the matrix above) with the following code. * * #define swapHiLo(word, temp) \ * temp = (word ^ (word >> 24)) & 0x000000ff; \ * word ^= temp | (temp << 24); * * right ^= temp = ((left << 8) ^ right) & 0xff00ff00; * left ^= temp >> 8; * swapHiLo(left, temp); * swapHiLo(right,temp); * * However, the two steps can be combined, so that the rows are rearranged * while the matrix is being flipped, reducing the number of bit exchange * operations from 8 ot 5. * * Initial Permutation */#define IP(left, right, temp) \ right ^= temp = ((left >> 4) ^ right) & 0x0f0f0f0f; \ left ^= temp << 4; \ right ^= temp = ((left >> 16) ^ right) & 0x0000ffff; \ left ^= temp << 16; \ right ^= temp = ((left << 2) ^ right) & 0xcccccccc; \ left ^= temp >> 2; \ right ^= temp = ((left << 8) ^ right) & 0xff00ff00; \ left ^= temp >> 8; \ right ^= temp = ((left >> 1) ^ right) & 0x55555555; \ left ^= temp << 1; /* The Final (Inverse Initial) permutation is done by reversing the ** steps of the Initital Permutation */#define FP(left, right, temp) \ right ^= temp = ((left >> 1) ^ right) & 0x55555555; \ left ^= temp << 1; \ right ^= temp = ((left << 8) ^ right) & 0xff00ff00; \ left ^= temp >> 8; \ right ^= temp = ((left << 2) ^ right) & 0xcccccccc; \ left ^= temp >> 2; \ right ^= temp = ((left >> 16) ^ right) & 0x0000ffff; \ left ^= temp << 16; \ right ^= temp = ((left >> 4) ^ right) & 0x0f0f0f0f; \ left ^= temp << 4; void DES_Do1Block(HALF * ks, BYTE * inbuf, BYTE * outbuf){ register HALF left, right; register HALF temp;#if defined(_X86_) left = HALFPTR(inbuf)[0]; right = HALFPTR(inbuf)[1]; BYTESWAP(left, temp); BYTESWAP(right, temp);#else if (((ptrdiff_t)inbuf & 0x03) == 0) { left = HALFPTR(inbuf)[0]; right = HALFPTR(inbuf)[1]; #if defined(IS_LITTLE_ENDIAN) BYTESWAP(left, temp); BYTESWAP(right, temp);#endif } else { left = ((HALF)inbuf[0] << 24) | ((HALF)inbuf[1] << 16) | ((HALF)inbuf[2] << 8) | inbuf[3]; right = ((HALF)inbuf[4] << 24) | ((HALF)inbuf[5] << 16) | ((HALF)inbuf[6] << 8) | inbuf[7]; }#endif IP(left, right, temp); /* shift the values left circularly 3 bits. */ left = (left << 3) | (left >> 29); right = (right << 3) | (right >> 29);#ifdef USE_INDEXING#define KSLOOKUP(s,b) SP[s][((temp >> (b+2)) & 0x3f)]#else#define KSLOOKUP(s,b) *(HALF*)((BYTE*)&SP[s][0]+((temp >> b) & 0xFC))#endif#define ROUND(out, in, r) \ temp = in ^ ks[2*r]; \ out ^= KSLOOKUP( 1, 24 ); \ out ^= KSLOOKUP( 3, 16 ); \ out ^= KSLOOKUP( 5, 8 ); \ out ^= KSLOOKUP( 7, 0 ); \ temp = ((in >> 4) | (in << 28)) ^ ks[2*r+1]; \ out ^= KSLOOKUP( 0, 24 ); \ out ^= KSLOOKUP( 2, 16 ); \ out ^= KSLOOKUP( 4, 8 ); \ out ^= KSLOOKUP( 6, 0 ); /* Do the 16 Feistel rounds */ ROUND(left, right, 0) ROUND(right, left, 1) ROUND(left, right, 2) ROUND(right, left, 3) ROUND(left, right, 4) ROUND(right, left, 5) ROUND(left, right, 6) ROUND(right, left, 7) ROUND(left, right, 8) ROUND(right, left, 9) ROUND(left, right, 10) ROUND(right, left, 11) ROUND(left, right, 12) ROUND(right, left, 13) ROUND(left, right, 14) ROUND(right, left, 15) /* now shift circularly right 3 bits to undo the shifting done ** above. switch left and right here. */ temp = (left >> 3) | (left << 29); left = (right >> 3) | (right << 29); right = temp; FP(left, right, temp);#if defined(_X86_) BYTESWAP(left, temp); BYTESWAP(right, temp); HALFPTR(outbuf)[0] = left; HALFPTR(outbuf)[1] = right; #else if (((ptrdiff_t)inbuf & 0x03) == 0) {#if defined(IS_LITTLE_ENDIAN) BYTESWAP(left, temp); BYTESWAP(right, temp);#endif HALFPTR(outbuf)[0] = left; HALFPTR(outbuf)[1] = right; } else { outbuf[0] = (BYTE)(left >> 24); outbuf[1] = (BYTE)(left >> 16); outbuf[2] = (BYTE)(left >> 8); outbuf[3] = (BYTE)(left ); outbuf[4] = (BYTE)(right >> 24); outbuf[5] = (BYTE)(right >> 16); outbuf[6] = (BYTE)(right >> 8); outbuf[7] = (BYTE)(right ); }#endif}/* Ackowledgements:** Two ideas used in this implementation were shown to me by Dennis Ferguson ** in 1990. He credits them to Richard Outerbridge and Dan Hoey. They were:** 1. The method of computing the Initial and Final permutations.** 2. Circularly rotating the SP tables and the initial values of left and ** right to reduce the number of shifts required during the 16 rounds.*/
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?