前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >DES加解密实现

DES加解密实现

作者头像
gaigai
发布2020-02-18 17:21:35
2.2K0
发布2020-02-18 17:21:35
举报
文章被收录于专栏:Windows开发Windows开发

对称加密算法包括DES、AES,其中DES算法的密钥56位(7字节)安全性较弱,于是产生3DES算法,3DES使用3个密钥,加密过程:用秘钥1进行DES加密,秘钥2进行DES解密,秘钥3进行DES加密;解密过程:用秘钥1进行DES解密,秘钥2进行DES加密,秘钥3进行DES解密。

DES加解密要求秘钥是8字节(每个字节的最后1位用于校验,秘钥是剩下的56位),加解密数据长度必须是8字节的整数倍,每8字节称为一个加解密块。如果不是8字节整数倍就要指定填充模式,常见填充模式有pkcs5padding、pkcs7padding、zeropadding。如果加解密数据包含多个块,在加解密某个块前可以指定跟前面的块进行某种计算,称为加密模式,常见有ECB和CBC。

网上有很多DES加解密的实现,但是能直接拿来使用的很少,本文介绍的是Richard Outerbridge的实现,其只实现8字节的数据加解密核心算法,对于长度不是8字节的倍数,需要填充到8的倍数,加密模式(ECB、CBC),需自己实现。它包含2个API:

第一,void deskey(unsigned char* hexkey[8], short mode),设定DES加解密的密钥和加密还是解密的标志。

第二,void des(unsigned char* from[8], unsigned char* to[8]),DES运算,加密运算还是解密运算由deskey接口mode指定,from指定源数据,to指定运算后数据。

接下来演示如何使用DES/3DES对字符串进行加解密,本演示代码使用的填充模式为自定义格式:明文长度(2字节)+明文内容+\0填充直到8的倍数,未采用加密模式(块之间加解密独立)。演示代码包含des算法实现(d3des.h和d3des.cpp)、demo代码(main.cpp)

main.cpp

代码语言:javascript
复制
#include "stdio.h"
#include <string>
#include "d3des.h"

int main() 
{
    // 下面这段明文的长度是15,不是8的倍数,加密前需要先填充成8的倍数,
    // 定义填充格式:明文长度(2字节)+明文内容+\0填充直到8的倍数
    std::string strPlainText = "I am plain text";
    int nBufferLength = 2 + strPlainText.length();
    if (nBufferLength % 8 != 0)
    {
        nBufferLength += (8 - nBufferLength % 8);
    }
    unsigned char* pPlainTextBuffer = new unsigned char[nBufferLength];    
    memset(pPlainTextBuffer, 0, nBufferLength);
    *((unsigned short*)pPlainTextBuffer) = strPlainText.length();
    memcpy(pPlainTextBuffer + 2, strPlainText.c_str(), strPlainText.length());

    // DES加密,然后解密验证跟明文相同
    unsigned char key[8];
    memcpy(key, "Iamkey1!", 8);
    deskey(key, EN0);  //设置秘钥,指定加密
    unsigned char* pCryptTextBuffer = new unsigned char[nBufferLength];
    for (int i = 0; i < nBufferLength / 8; i++)
    {
        des(pPlainTextBuffer + i * 8, pCryptTextBuffer + i * 8);  //加密
    }

    deskey(key, DE1);  //设置秘钥,指定解密
    unsigned char* pPlainTextBuffer2 = new unsigned char[nBufferLength];
    for (int i = 0; i < nBufferLength / 8; i++)
    {
        des(pCryptTextBuffer + i * 8, pPlainTextBuffer2 + i * 8);  //解密
    }

    // 根据填充格式获得明文
    strPlainText = std::string((const char*)(pPlainTextBuffer2 + 2), *((unsigned short*)pPlainTextBuffer2));
    printf("des encrypt, then decrypt, the plain text is %s \n", strPlainText.c_str());

    // 3DES加密,先用key1加密,再用key2解密,最后用key3加密
    unsigned char keys[24];
    memcpy(keys, "Iamkey1!Iamkey2!Iamkey3!", 24);
    deskey(keys, EN0);  //设置秘钥,指定加密
    for (int i = 0; i < nBufferLength / 8; i++)
    {
        des(pPlainTextBuffer + i * 8, pCryptTextBuffer + i * 8);  //加密
    }

    deskey(keys+8, DE1);  //设置秘钥,指定解密
    for (int i = 0; i < nBufferLength / 8; i++)
    {
        des(pCryptTextBuffer + i * 8, pCryptTextBuffer + i * 8);  //解密
    }

    deskey(keys + 16, DE1);  //设置秘钥,指定加密
    for (int i = 0; i < nBufferLength / 8; i++)
    {
        des(pCryptTextBuffer + i * 8, pCryptTextBuffer + i * 8);  //加密
    }   

    delete[] pPlainTextBuffer;
    delete[] pCryptTextBuffer;
    delete[] pPlainTextBuffer2;

    return 0;
}

d3des.h

代码语言:javascript
复制
/* d3des.h -
 *
 *  Headers and defines for d3des.c
 *  Graven Imagery, 1992.
 *
 * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge
 *  (GEnie : OUTER; CIS : [71755,204])
 */

#define D2_DES    /* include double-length support */
#define D3_DES    /* include triple-length support */

#ifdef D3_DES
#ifndef D2_DES
#define D2_DES    /* D2_DES is needed for D3_DES */
#endif
#endif

#define EN0  0  /* MODE == encrypt */
#define DE1  1  /* MODE == decrypt */

/* A useful alias on 68000-ish machines, but NOT USED HERE. */
/*
typedef union {
  unsigned long blok[2];
  unsigned short word[4];
  unsigned char byte[8];
  } M68K;*/

extern void deskey(unsigned char *, short);//得到加密/解密码(56bits)
/*          hexkey[8]     MODE
 * Sets the internal key register according to the hexadecimal
 * key contained in the 8 bytes of hexkey, according to the DES,
 * for encryption or decryption according to MODE.
 */

extern void usekey(unsigned long *);
/*        cookedkey[32]
 * Loads the internal key register with the data in cookedkey.
 */

extern void cpkey(unsigned long *);
/*       cookedkey[32]
 * Copies the contents of the internal key register into the storage
 * located at &cookedkey[0].
 */

extern void des(unsigned char *, unsigned char *);
/*        from[8]        to[8]
 * Encrypts/Decrypts (according to the key currently loaded in the
 * internal key register) one block of eight bytes at address 'from'
 * into the block at address 'to'.  They can be the same.
 */

#ifdef D2_DES

#define desDkey(a,b)  des2key((a),(b))
extern void des2key(unsigned char *, short);
/*          hexkey[16]     MODE
 * Sets the internal key registerS according to the hexadecimal
 * keyS contained in the 16 bytes of hexkey, according to the DES,
 * for DOUBLE encryption or decryption according to MODE.
 * NOTE: this clobbers all three key registers!
 */

extern void Ddes(unsigned char *, unsigned char *);
/*        from[8]        to[8]
 * Encrypts/Decrypts (according to the keyS currently loaded in the
 * internal key registerS) one block of eight bytes at address 'from'
 * into the block at address 'to'.  They can be the same.
 */

extern void D2des(unsigned char *, unsigned char *);
/*        from[16]        to[16]
 * Encrypts/Decrypts (according to the keyS currently loaded in the
 * internal key registerS) one block of SIXTEEN bytes at address 'from'
 * into the block at address 'to'.  They can be the same.
 */

extern void makekey(char *, unsigned char *);
/*    *password,  single-length key[8]
 * With a double-length default key, this routine hashes a NULL-terminated
 * string into an eight-byte random-looking key, suitable for use with the
 * deskey() routine.
 */

#define makeDkey(a,b)  make2key((a),(b))
extern void make2key(char *, unsigned char *);
/*    *password,  double-length key[16]
 * With a double-length default key, this routine hashes a NULL-terminated
 * string into a sixteen-byte random-looking key, suitable for use with the
 * des2key() routine.
 */

#ifndef D3_DES  /* D2_DES only */

#define useDkey(a)  use2key((a))
#define cpDkey(a)  cp2key((a))

extern void use2key(unsigned long *);
/*        cookedkey[64]
 * Loads the internal key registerS with the data in cookedkey.
 * NOTE: this clobbers all three key registers!
 */

extern void cp2key(unsigned long *);
/*       cookedkey[64]
 * Copies the contents of the internal key registerS into the storage
 * located at &cookedkey[0].
 */

#else  /* D3_DES too */

#define useDkey(a)  use3key((a))
#define cpDkey(a)  cp3key((a))

extern void des3key(unsigned char *, short);
/*          hexkey[24]     MODE
 * Sets the internal key registerS according to the hexadecimal
 * keyS contained in the 24 bytes of hexkey, according to the DES,
 * for DOUBLE encryption or decryption according to MODE.
 */

extern void use3key(unsigned long *);
/*        cookedkey[96]
 * Loads the 3 internal key registerS with the data in cookedkey.
 */

extern void cp3key(unsigned long *);
/*       cookedkey[96]
 * Copies the contents of the 3 internal key registerS into the storage
 * located at &cookedkey[0].
 */

extern void make3key(char *, unsigned char *);
/*    *password,  triple-length key[24]
 * With a triple-length default key, this routine hashes a NULL-terminated
 * string into a twenty-four-byte random-looking key, suitable for use with
 * the des3key() routine.
 */

#endif  /* D3_DES */
#endif  /* D2_DES */

/* d3des.h V5.09 rwo 9208.04 15:06 Graven Imagery
 ********************************************************************/

d3des.cpp

代码语言:javascript
复制
/* D3DES (V5.09) -
 *
 * A portable, public domain, version of the Data Encryption Standard.
 *
 * Written with Symantec's THINK (Lightspeed) C by Richard Outerbridge.
 * Thanks to: Dan Hoey for his excellent Initial and Inverse permutation
 * code;  Jim Gillogly & Phil Karn for the DES key schedule code; Dennis
 * Ferguson, Eric Young and Dana How for comparing notes; and Ray Lau,
 * for humouring me on.
 *
 * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge.
 * (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992.
 */

#include "d3des.h"

static void scrunch(unsigned char *, unsigned long *);
static void unscrun(unsigned long *, unsigned char *);
static void desfunc(unsigned long *, unsigned long *);
static void cookey(unsigned long *);

static unsigned long KnL[32] = { 0L };
static unsigned long KnR[32] = { 0L };
static unsigned long Kn3[32] = { 0L };
static unsigned char Df_Key[24] = {
  0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,
  0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10,
  0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67 };

static unsigned short bytebit[8]  = {
  0200, 0100, 040, 020, 010, 04, 02, 01 };

static unsigned long bigbyte[24] = {
  0x800000L,  0x400000L,  0x200000L,  0x100000L,
  0x80000L,  0x40000L,  0x20000L,  0x10000L,
  0x8000L,  0x4000L,  0x2000L,  0x1000L,
  0x800L,   0x400L,   0x200L,   0x100L,
  0x80L,    0x40L,    0x20L,    0x10L,
  0x8L,    0x4L,    0x2L,    0x1L  };

/* Use the key schedule specified in the Standard (ANSI X3.92-1981). */

static unsigned char pc1[56] = {
  56, 48, 40, 32, 24, 16,  8,   0, 57, 49, 41, 33, 25, 17,
   9,  1, 58, 50, 42, 34, 26,  18, 10,  2, 59, 51, 43, 35,
  62, 54, 46, 38, 30, 22, 14,   6, 61, 53, 45, 37, 29, 21,
  13,  5, 60, 52, 44, 36, 28,  20, 12,  4, 27, 19, 11,  3 };

static unsigned char totrot[16] = {
  1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 };

static unsigned char pc2[48] = {
  13, 16, 10, 23,  0,  4,  2, 27, 14,  5, 20,  9,
  22, 18, 11,  3, 25,  7, 15,  6, 26, 19, 12,  1,
  40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
  43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 };

void deskey(unsigned char *key, short edf)  /* Thanks to James Gillogly & Phil Karn! */
{
  register int i, j, l, m, n;
  unsigned char pc1m[56], pcr[56];
  unsigned long kn[32];

  for ( j = 0; j < 56; j++ ) {
    l = pc1[j];
    m = l & 07;
    pc1m[j] = (key[l >> 3] & bytebit[m]) ? 1 : 0;
    }
  for( i = 0; i < 16; i++ ) {
    if( edf == DE1 ) m = (15 - i) << 1;
    else m = i << 1;
    n = m + 1;
    kn[m] = kn[n] = 0L;
    for( j = 0; j < 28; j++ ) {
      l = j + totrot[i];
      if( l < 28 ) pcr[j] = pc1m[l];
      else pcr[j] = pc1m[l - 28];
      }
    for( j = 28; j < 56; j++ ) {
        l = j + totrot[i];
        if( l < 56 ) pcr[j] = pc1m[l];
        else pcr[j] = pc1m[l - 28];
        }
    for( j = 0; j < 24; j++ ) {
      if( pcr[pc2[j]] ) kn[m] |= bigbyte[j];
      if( pcr[pc2[j+24]] ) kn[n] |= bigbyte[j];
      }
    }
  cookey(kn);
  return;
  }

static void cookey(register unsigned long *raw1)
{
  register unsigned long *cook, *raw0;
  unsigned long dough[32];
  register int i;

  cook = dough;
  for( i = 0; i < 16; i++, raw1++ ) {
    raw0 = raw1++;
    *cook   = (*raw0 & 0x00fc0000L) << 6;
    *cook  |= (*raw0 & 0x00000fc0L) << 10;
    *cook  |= (*raw1 & 0x00fc0000L) >> 10;
    *cook++ |= (*raw1 & 0x00000fc0L) >> 6;
    *cook   = (*raw0 & 0x0003f000L) << 12;
    *cook  |= (*raw0 & 0x0000003fL) << 16;
    *cook  |= (*raw1 & 0x0003f000L) >> 4;
    *cook++ |= (*raw1 & 0x0000003fL);
    }
  usekey(dough);
  return;
  }

void cpkey(register unsigned long *into)
{
  register unsigned long *from, *endp;

  from = KnL, endp = &KnL[32];
  while( from < endp ) *into++ = *from++;
  return;
  }

void usekey(register unsigned long *from)
{
  register unsigned long *to, *endp;

  to = KnL, endp = &KnL[32];
  while( to < endp ) *to++ = *from++;
  return;
  }

void des(unsigned char *inblock, unsigned char *outblock)
{
  unsigned long work[2];

  scrunch(inblock, work);
  desfunc(work, KnL);
  unscrun(work, outblock);
  return;
  }

static void scrunch(register unsigned char *outof, register unsigned long *into)
{
  *into   = (*outof++ & 0xffL) << 24;
  *into  |= (*outof++ & 0xffL) << 16;
  *into  |= (*outof++ & 0xffL) << 8;
  *into++ |= (*outof++ & 0xffL);
  *into   = (*outof++ & 0xffL) << 24;
  *into  |= (*outof++ & 0xffL) << 16;
  *into  |= (*outof++ & 0xffL) << 8;
  *into  |= (*outof   & 0xffL);
  return;
  }

static void unscrun(register unsigned long *outof, register unsigned char *into)
{
  *into++ = (unsigned char)((*outof >> 24) & 0xffL);
  *into++ = (unsigned char)((*outof >> 16) & 0xffL);
  *into++ = (unsigned char)((*outof >>  8) & 0xffL);
  *into++ = (unsigned char)(*outof++   & 0xffL);
  *into++ = (unsigned char)((*outof >> 24) & 0xffL);
  *into++ = (unsigned char)((*outof >> 16) & 0xffL);
  *into++ = (unsigned char)((*outof >>  8) & 0xffL);
  *into  = (unsigned char)(*outof & 0xffL);
  return;
  }

static unsigned long SP1[64] = {
  0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L,
  0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L,
  0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L,
  0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L,
  0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L,
  0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L,
  0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L,
  0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L,
  0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L,
  0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L,
  0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L,
  0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L,
  0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L,
  0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L,
  0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L,
  0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L };

static unsigned long SP2[64] = {
  0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L,
  0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L,
  0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L,
  0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L,
  0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L,
  0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L,
  0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L,
  0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L,
  0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L,
  0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L,
  0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L,
  0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L,
  0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L,
  0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L,
  0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L,
  0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L };

static unsigned long SP3[64] = {
  0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L,
  0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L,
  0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L,
  0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L,
  0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L,
  0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L,
  0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L,
  0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L,
  0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L,
  0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L,
  0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L,
  0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L,
  0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L,
  0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L,
  0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L,
  0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L };

static unsigned long SP4[64] = {
  0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
  0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L,
  0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L,
  0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L,
  0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L,
  0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L,
  0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L,
  0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L,
  0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L,
  0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L,
  0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L,
  0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
  0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L,
  0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L,
  0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L,
  0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L };

static unsigned long SP5[64] = {
  0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L,
  0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L,
  0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L,
  0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L,
  0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L,
  0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L,
  0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L,
  0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L,
  0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L,
  0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L,
  0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L,
  0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L,
  0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L,
  0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L,
  0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L,
  0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L };

static unsigned long SP6[64] = {
  0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L,
  0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L,
  0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L,
  0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L,
  0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L,
  0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L,
  0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L,
  0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L,
  0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L,
  0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L,
  0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L,
  0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L,
  0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L,
  0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L,
  0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L,
  0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L };

static unsigned long SP7[64] = {
  0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L,
  0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L,
  0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L,
  0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L,
  0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L,
  0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L,
  0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L,
  0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L,
  0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L,
  0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L,
  0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L,
  0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L,
  0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L,
  0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L,
  0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L,
  0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L };

static unsigned long SP8[64] = {
  0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L,
  0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L,
  0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L,
  0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L,
  0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L,
  0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L,
  0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L,
  0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L,
  0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L,
  0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L,
  0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L,
  0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L,
  0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L,
  0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L,
  0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L,
  0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L };

static void desfunc(register unsigned long *block, register unsigned long *keys)
{
  register unsigned long fval, work, right, leftt;
  register int round;

  leftt = block[0];
  right = block[1];
  work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL;
  right ^= work;
  leftt ^= (work << 4);
  work = ((leftt >> 16) ^ right) & 0x0000ffffL;
  right ^= work;
  leftt ^= (work << 16);
  work = ((right >> 2) ^ leftt) & 0x33333333L;
  leftt ^= work;
  right ^= (work << 2);
  work = ((right >> 8) ^ leftt) & 0x00ff00ffL;
  leftt ^= work;
  right ^= (work << 8);
  right = ((right << 1) | ((right >> 31) & 1L)) & 0xffffffffL;
  work = (leftt ^ right) & 0xaaaaaaaaL;
  leftt ^= work;
  right ^= work;
  leftt = ((leftt << 1) | ((leftt >> 31) & 1L)) & 0xffffffffL;

  for( round = 0; round < 8; round++ ) {
    work  = (right << 28) | (right >> 4);
    work ^= *keys++;
    fval  = SP7[ work     & 0x3fL];
    fval |= SP5[(work >>  8) & 0x3fL];
    fval |= SP3[(work >> 16) & 0x3fL];
    fval |= SP1[(work >> 24) & 0x3fL];
    work  = right ^ *keys++;
    fval |= SP8[ work     & 0x3fL];
    fval |= SP6[(work >>  8) & 0x3fL];
    fval |= SP4[(work >> 16) & 0x3fL];
    fval |= SP2[(work >> 24) & 0x3fL];
    leftt ^= fval;
    work  = (leftt << 28) | (leftt >> 4);
    work ^= *keys++;
    fval  = SP7[ work     & 0x3fL];
    fval |= SP5[(work >>  8) & 0x3fL];
    fval |= SP3[(work >> 16) & 0x3fL];
    fval |= SP1[(work >> 24) & 0x3fL];
    work  = leftt ^ *keys++;
    fval |= SP8[ work     & 0x3fL];
    fval |= SP6[(work >>  8) & 0x3fL];
    fval |= SP4[(work >> 16) & 0x3fL];
    fval |= SP2[(work >> 24) & 0x3fL];
    right ^= fval;
    }

  right = (right << 31) | (right >> 1);
  work = (leftt ^ right) & 0xaaaaaaaaL;
  leftt ^= work;
  right ^= work;
  leftt = (leftt << 31) | (leftt >> 1);
  work = ((leftt >> 8) ^ right) & 0x00ff00ffL;
  right ^= work;
  leftt ^= (work << 8);
  work = ((leftt >> 2) ^ right) & 0x33333333L;
  right ^= work;
  leftt ^= (work << 2);
  work = ((right >> 16) ^ leftt) & 0x0000ffffL;
  leftt ^= work;
  right ^= (work << 16);
  work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL;
  leftt ^= work;
  right ^= (work << 4);
  *block++ = right;
  *block = leftt;
  return;
  }

#ifdef D2_DES

void des2key(unsigned char *hexkey, short mode)    /* stomps on Kn3 too */
       /* unsigned char[16] */
{
  short revmod;

  revmod = (mode == EN0) ? DE1 : EN0;
  deskey(&hexkey[8], revmod);
  cpkey(KnR);
  deskey(hexkey, mode);
  cpkey(Kn3);          /* Kn3 = KnL */
  return;
  }

void Ddes(unsigned char *from, unsigned char *into)
        /* unsigned char[8] */
{
  unsigned long work[2];

  scrunch(from, work);
  desfunc(work, KnL);
  desfunc(work, KnR);
  desfunc(work, Kn3);
  unscrun(work, into);
  return;
  }

void D2des(unsigned char *from, unsigned char *into)
      /* unsigned char[16] */
      /* unsigned char[16] */
{
  unsigned long *right, *l1, swap;
  unsigned long leftt[2], bufR[2];

  right = bufR;
  l1 = &leftt[1];
  scrunch(from, leftt);
  scrunch(&from[8], right);
  desfunc(leftt, KnL);
  desfunc(right, KnL);
  swap = *l1;
  *l1 = *right;
  *right = swap;
  desfunc(leftt, KnR);
  desfunc(right, KnR);
  swap = *l1;
  *l1 = *right;
  *right = swap;
  desfunc(leftt, Kn3);
  desfunc(right, Kn3);
  unscrun(leftt, into);
  unscrun(right, &into[8]);
  return;
  }

void makekey(register char *aptr, register unsigned char *kptr)
        /* NULL-terminated  */
            /* unsigned char[8] */
{
  register unsigned char *store;
  register int first, i;
  unsigned long savek[96];

  cpDkey(savek);
  des2key(Df_Key, EN0);
  for( i = 0; i < 8; i++ ) kptr[i] = Df_Key[i];
  first = 1;
  while( (*aptr != '\0') || first ) {
    store = kptr;
    for( i = 0; i < 8 && (*aptr != '\0'); i++ ) {
      *store++ ^= *aptr & 0x7f;
      *aptr++ = '\0';
      }
    Ddes(kptr, kptr);
    first = 0;
    }
  useDkey(savek);
  return;
  }

void make2key(register char *aptr, register unsigned char *kptr)
        /* NULL-terminated   */
        /* unsigned char[16] */
{
  register unsigned char *store;
  register int first, i;
  unsigned long savek[96];

  cpDkey(savek);
  des2key(Df_Key, EN0);
  for( i = 0; i < 16; i++ ) kptr[i] = Df_Key[i];
  first = 1;
  while( (*aptr != '\0') || first ) {
    store = kptr;
    for( i = 0; i < 16 && (*aptr != '\0'); i++ ) {
      *store++ ^= *aptr & 0x7f;
      *aptr++ = '\0';
      }
    D2des(kptr, kptr);
    first = 0;
    }
  useDkey(savek);
  return;
  }

#ifndef D3_DES  /* D2_DES only */
#ifdef  D2_DES  /* iff D2_DES! */

void cp2key(register unsigned long *into)
      /* unsigned long[64] */
{
  register unsigned long *from, *endp;

  cpkey(into);
  into = &into[32];
  from = KnR, endp = &KnR[32];
  while( from < endp ) *into++ = *from++;
  return;
  }

void use2key(register unsigned long *from)        /* stomps on Kn3 too */
      /* unsigned long[64] */
{
  register unsigned long *to, *endp;

  usekey(from);
  from = &from[32];
  to = KnR, endp = &KnR[32];
  while( to < endp ) *to++ = *from++;
  cpkey(Kn3);          /* Kn3 = KnL */
  return;
  }

#endif  /* iff D2_DES */
#else  /* D3_DES too */

static void D3des(unsigned char *, unsigned char *);

void des3key(unsigned char *hexkey, short mode)
      /* unsigned char[24] */
{
  unsigned char *first, *third;
  short revmod;

  if( mode == EN0 ) {
    revmod = DE1;
    first = hexkey;
    third = &hexkey[16];
    }
  else {
    revmod = EN0;
    first = &hexkey[16];
    third = hexkey;
    }
  deskey(&hexkey[8], revmod);
  cpkey(KnR);
  deskey(third, mode);
  cpkey(Kn3);
  deskey(first, mode);
  return;
  }

void cp3key(register unsigned long *into)
      /* unsigned long[96] */
{
  register unsigned long *from, *endp;

  cpkey(into);
  into = &into[32];
  from = KnR, endp = &KnR[32];
  while( from < endp ) *into++ = *from++;
  from = Kn3, endp = &Kn3[32];
  while( from < endp ) *into++ = *from++;
  return;
  }

void use3key(register unsigned long *from)
      /* unsigned long[96] */
{
  register unsigned long *to, *endp;

  usekey(from);
  from = &from[32];
  to = KnR, endp = &KnR[32];
  while( to < endp ) *to++ = *from++;
  to = Kn3, endp = &Kn3[32];
  while( to < endp ) *to++ = *from++;
  return;
  }

static void D3des(unsigned char *from, unsigned char *into)  /* amateur theatrics */
          /* unsigned char[24] */
          /* unsigned char[24] */
{
  unsigned long swap, leftt[2], middl[2], right[2];

  scrunch(from, leftt);
  scrunch(&from[8], middl);
  scrunch(&from[16], right);
  desfunc(leftt, KnL);
  desfunc(middl, KnL);
  desfunc(right, KnL);
  swap = leftt[1];
  leftt[1] = middl[0];
  middl[0] = swap;
  swap = middl[1];
  middl[1] = right[0];
  right[0] = swap;
  desfunc(leftt, KnR);
  desfunc(middl, KnR);
  desfunc(right, KnR);
  swap = leftt[1];
  leftt[1] = middl[0];
  middl[0] = swap;
  swap = middl[1];
  middl[1] = right[0];
  right[0] = swap;
  desfunc(leftt, Kn3);
  desfunc(middl, Kn3);
  desfunc(right, Kn3);
  unscrun(leftt, into);
  unscrun(middl, &into[8]);
  unscrun(right, &into[16]);
  return;
  }

void make3key(register char *aptr, register unsigned char *kptr)
        /* NULL-terminated   */
        /* unsigned char[24] */
{
  register unsigned char *store;
  register int first, i;
  unsigned long savek[96];

  cp3key(savek);
  des3key(Df_Key, EN0);
  for( i = 0; i < 24; i++ ) kptr[i] = Df_Key[i];
  first = 1;
  while( (*aptr != '\0') || first ) {
    store = kptr;
    for( i = 0; i < 24 && (*aptr != '\0'); i++ ) {
      *store++ ^= *aptr & 0x7f;
      *aptr++ = '\0';
      }
    D3des(kptr, kptr);
    first = 0;
    }
  use3key(savek);
  return;
  }

#endif  /* D3_DES */
#endif  /* D2_DES */

/* Validation sets:
 *
 * Single-length key, single-length plaintext -
 * Key    : 0123 4567 89ab cdef
 * Plain  : 0123 4567 89ab cde7
 * Cipher : c957 4425 6a5e d31d
 *
 * Double-length key, single-length plaintext -
 * Key    : 0123 4567 89ab cdef fedc ba98 7654 3210
 * Plain  : 0123 4567 89ab cde7
 * Cipher : 7f1d 0a77 826b 8aff
 *
 * Double-length key, double-length plaintext -
 * Key    : 0123 4567 89ab cdef fedc ba98 7654 3210
 * Plain  : 0123 4567 89ab cdef 0123 4567 89ab cdff
 * Cipher : 27a0 8440 406a df60 278f 47cf 42d6 15d7
 *
 * Triple-length key, single-length plaintext -
 * Key    : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567
 * Plain  : 0123 4567 89ab cde7
 * Cipher : de0b 7c06 ae5e 0ed5
 *
 * Triple-length key, double-length plaintext -
 * Key    : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567
 * Plain  : 0123 4567 89ab cdef 0123 4567 89ab cdff
 * Cipher : ad0d 1b30 ac17 cf07 0ed1 1c63 81e4 4de5
 *
 * d3des V5.0a rwo 9208.07 18:44 Graven Imagery
 **********************************************************************/
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-01-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Windows开发 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档