密码学大作业——NS认证协议

DES + C++ Socket + NS认证

对称密码采用DES加密。Windows环境下的C++Socket,实现NS认证。具体还原的场景是,User1向KDC请求与User2进行连接,KDC分发给User1密钥。User1用KDC下发的信息转交给User2,并与User2进行交互验证。在过程中,User1被视为Client,User2与KDC均视为Server。

  • DES.cpp

#include <algorithm>
#include <bitset>
#include <iostream>
#include <string>
using namespace std;

/**
 *数据初始置换表
 */
int T1[8][8] = {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};
/**
 *密钥初始置换表
 */
int T2[8][7] = {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,
                3,  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};

/**
 *密钥循环左移位数表
 */
int T3[16] = {1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1};

/**
 *密钥压缩置换表
 */
int T4[8][6] = {14, 17, 11, 24, 1,  5,  3,  28, 15, 6,  21, 10, 23, 19, 12, 4,
                26, 8,  16, 7,  27, 20, 13, 2,  41, 52, 31, 37, 47, 55, 30, 40,
                51, 45, 33, 48, 44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32};

/**
 *数据扩展表
 */
int T5[8][6] = {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};

/**
 *S盒置换表
 */
int S[8][4][16] = {{{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}}};

/**
 *P盒置换表
 */
int P[4][8] = {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};

/**

 *最终置换表

 */
int T6[8][8] = {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};

/**

 *最终置换函数 64位->64位

 *函数说明:s为完成最后一轮循环得到的64为数据

 *返回值为密文或明文

 */

class des {
 private:
  string desKeys[20];

 public:
  string final_permutation(string s) {
    string rs = "";
    for (int i = 0; i < 8; i++) {
      for (int j = 0; j < 8; j++) {
        rs += s[T6[i][j] - 1];
      }
    }
    return rs;
  }

  /**

   *P盒置换函数 32位->32位

   *函数说明:s为S盒的输出

   */
  string P_box(string s) {
    string rs = "";
    for (int i = 0; i < 4; i++) {
      for (int j = 0; j < 8; j++) {
        rs += (s[P[i][j] - 1]);
      }
    }
    return rs;
  }

  /**

   *S盒置换函数 48位->32位

   *函数说明:s为48位数据

   *返回值为32位

   */
  string S_box(string s) {
    string rs = "";
    string s1;
    int k1, k2;  // S盒的行号和列号
    int h = 1;   //决定使用那个S盒
    for (int i = 0; i <= 42; i = i + 6, h++) {
      k1 = (s[i] - '0') * 2 + (s[i + 5] - '0') * 1;
      k2 = (s[i + 1] - '0') * 8 + (s[i + 2] - '0') * 4 + (s[i + 3] - '0') * 2 +
           (s[i + 4] - '0') * 1;
      int x = S[h - 1][k1][k2];
      s1 = "";
      int y = 8;
      for (int j = 1; j <= 4; j++) {
        if (x < y) {
          s1 += "0";
          y /= 2;
        } else {
          s1 += "1";
          x = x % y;
          y /= 2;
        }
      }
      rs += s1;
    }
    return rs;
  }

  /**

   *异或运算函数

   *要求位数相同

   */
  string desXOR(string s1, string s2) {
    string rs = "";
    for (int i = 0; i < s1.length() && i < s2.length(); i++) {
      rs += ((s1[i] - '0') ^ (s2[i] - '0')) + '0';
    }
    return rs;
  }

  /**

   *数据扩展函数 32->48

   *函数说明:s为数据的右半部分 32位

   *扩展成48位的输出

   */
  string plaintext_righthalf_extended_permutation(string s) {
    string rs = "";
    for (int i = 0; i < 8; i++) {
      for (int j = 0; j < 6; j++) {
        rs += s[T5[i][j] - 1];
      }
    }
    return rs;
  }

  /**

   *密钥压缩置换函数 56位->48位

   *函数说明:s为56为的密钥

   *输出为48位的子密钥

   */
  string secret_key_compression_replacement(string s) {
    string rs = "";
    // printf("密钥:%s\n", s);
    for (int i = 0; i < 8; i++) {
      for (int j = 0; j < 6; j++) {
        rs += s[T4[i][j] - 1];
      }
    }
    return rs;
  }

  /**

   *密钥循环左移函数 56位->56位

   *函数说明:k为左移位数 s为密钥

   *返回值位数不变

   */
  string secret_ket_left_move(int k, string s)  //密钥循环左移k位
  {
    string s1 = s.substr(0, 28);
    string s2 = s.substr(28, 28);
    string rs = s1.substr(k, 28 - k) + s1.substr(0, k) + s2.substr(k, 28 - k) +
                s2.substr(0, k);
    return rs;
  }

  /**

   *密钥初始置换函数 64位->56位

   *函数说明:s为64位的初始密钥

   *返回值为56位

   */
  string secret_key_initial_permutation(string s) {
    string rs = "";
    for (int i = 0; i < 8; i++) {
      for (int j = 0; j < 7; j++) {
        rs += s[T2[i][j] - 1];
      }
    }

    return rs;
  }

  /**

   *明文初始置换函数 64位->64位

   *函数说明:s为初始明文 64位

   *返回值为6位

   */
  string plaintext_initial_permutation(string s)  //明文初始置换
  {
    string rs = "";
    for (int i = 0; i < 8; i++) {
      for (int j = 0; j < 8; j++) {
        rs += s[T1[i][j] - 1];
      }
    }
    return rs;
  }

  /**

   *16进制转2进制函数

   *函数说明:s为16进制字符串

   *返回为2进制字符串

   */
  string des_H(string s) {
    string s1;
    string rs = "";
    for (int i = 0; i < s.length(); i++) {
      int x;
      if (s[i] >= '0' && s[i] <= '9') {
        x = s[i] - '0';
      } else {
        x = s[i] - 'A' + 10;
      }
      s1 = "";
      int y = 8;
      for (int j = 1; j <= 4; j++) {
        if (x < y) {
          y /= 2;
          s1 += "0";
        } else {
          s1 += "1";
          x = x % y;
          y = y / 2;
        }
      }
      rs += s1;
    }
    return rs;
  }

  /**

  *2进制转16进制函数

  *str为2进制字符串

  *返回值为16进制字符串

  */
  string des_G(string str) {
    string rs = "";
    char temp;
    for (int i = 0; i <= str.length() - 4; i = i + 4) {
      int x = (str[i] - '0') * 8 + (str[i + 1] - '0') * 4 +
              (str[i + 2] - '0') * 2 + str[i + 3] - '0';

      if (x >= 10) {
        temp = (char)(x - 10 + 'A');
      } else {
        temp = (char)(x + '0');
      }
      rs += temp;
    }
    return rs;
  }

  /**

   *封装函数f

   *函数说明:接收32位数据和48位的子密钥 产生一个32位的输出

   *str1:32位数据  str2:48位的子密钥

   *返回值32位

   */

  string des_f(string str1, string str2) {
    string expendR = plaintext_righthalf_extended_permutation(str1);
    // cout<<"32位数据扩展为48位结果:"<<expendR<<endl;

    string rs = desXOR(expendR, str2);
    // cout<<"密钥和扩展数据异或结果:"<<rs<<endl;

    rs = S_box(rs);
    // cout<<"S盒替代结果(48->32):"<<rs<<endl;

    rs = P_box(rs);
    // cout<<"P盒替代结果(32->32):"<<rs<<endl;

    return rs;
  }

  /**

   *子密钥生成函数

   *函数说明:s为给定的密钥

   *生成16个子密钥

   */

  void des_generateKeys(string s) {
    s = secret_key_initial_permutation(s);

    for (int i = 1; i <= 16; i++) {
      s = secret_ket_left_move(T3[i - 1], s);
      desKeys[i] = secret_key_compression_replacement(s);
    }
  }
  /*
   * 明文字符串转换成0/1字符串
   */
  string des_StrToBitStr(string str) {
    bitset<64> bstr;
    for (int i = 0; i < 8; i++) {
      bitset<8> bits = bitset<8>(str[i]);
      for (int j = 0; j < 8; j++) {
        bstr[i * 8 + j] = bits[7 - j];
      }
    }
    string s = bstr.to_string();
    //添加一个翻转操作
    reverse(begin(s), end(s));
    return s;
  }
  /*
   * 0/1字符串装换为字符形式的字符串
   */
  string des_BitStrToStr(string bstr) {
    string str = "";
    //每八位转化成十进制,然后将数字结果转化成字符
    int sum;
    for (int i = 0; i < bstr.size(); i += 8) {
      sum = 0;
      for (int j = 0; j < 8; j++)
        if (bstr[i + j] == '1')
          sum = sum * 2 + 1;
        else
          sum = sum * 2;
      str = str + char(sum);
    }
    return str;
  }

  string chardeel(string &str1, string &str2) {
    string temp_str = "";
    int divi_times = (str1.size() % 8 ? str1.size() / 8 + 1
                                      : str1.size() / 8);  //计算分组个数
    for (int i = 0; i < divi_times; ++i) {  //每个分组单独转换成二进制串
      string str1_temp = str1.substr(8 * i, 8);  // substr(start,len)

      bool jude = false;
      int addchar = 0;
      if (str1_temp.size() % 8) {
        jude = true;
        addchar = 8 - str1_temp.size() % 8;
      }
      int sub = str1_temp.size() * 8;
      if (jude) {
        for (int i = 0; i < addchar; ++i) {
          str1_temp += 'a';
        }
      }
      str1_temp = des_StrToBitStr(str1_temp);
      if (jude) {
        for (int i = 0; i < addchar * 8; ++i) {
          str1_temp[sub + i] = '0';
        }
      }
      temp_str = temp_str + str1_temp;
    }
    str2 = des_H(str2);
    return temp_str;
  }

  /**

   *DES加密函数 64位->64位

   *函数说明:str1为64位的给定明文

   *返回值为64位的密文

   */

  string des_encrypt(string str1, string str2) {
    str1 = chardeel(str1, str2);  //明文分组和填充,返回01字符串

    des_generateKeys(str2);  //生成16个子密钥

    int divi_times = str1.size() / 64;  //分成多少组去进行des
    string rs_temp = "";

    for (int i = 0; i < divi_times; ++i) {
      string str1_temp = str1.substr(i * 64, 64);

      //第一步:明文初始置换 64->64
      str1_temp = plaintext_initial_permutation(str1_temp);

      //第二步:数据分组
      string left = str1_temp.substr(0, 32);
      string right = str1_temp.substr(32, 32);
      string newleft;
      // printf("开始迭代!\n");
      //第三步:16轮迭代
      for (int i = 1; i <= 16; i++) {
        newleft = right;
        right = desXOR(left, des_f(right, desKeys[i]));
        // printf("第%d组子密钥:%s\n", i, desKeys[i]);
        left = newleft;
      }

      //第四步:合并数据 注意位R16L16
      string rs = right + left;

      //结尾置换
      rs = final_permutation(rs);
      rs_temp = rs_temp + rs;
    }
    return rs_temp;
  }
  /**

  *解密函数

  *str为密文

  *输出明文

  */
  string des_decrypt(string str, string key) {
    cout << "正在解密……" << endl;
    key = des_H(key);
    des_generateKeys(key);             //生成16个子密钥
    int divi_times = str.size() / 64;  //分成多少组去进行des
    string rs_temp = "";

    for (int i = 0; i < divi_times; ++i) {
      string str_temp = str.substr(i * 64, 64);
      //把密文当作明文进行初始明文置换
      str_temp = plaintext_initial_permutation(str_temp);

      //左右分组
      string left = str_temp.substr(0, 32);
      string right = str_temp.substr(32, 32);

      string newleft;

      //逆序的子密钥使用 16轮迭代
      for (int i = 16; i >= 1; i--) {
        newleft = right;
        right = desXOR(left, des_f(right, desKeys[i]));
        left = newleft;
      }

      //合并
      string rs = right + left;

      //最后置换
      rs = final_permutation(rs);
      rs_temp = rs_temp + rs;
    }

    rs_temp = des_BitStrToStr(rs_temp);
    cout << "解密成功!" << endl;
    return rs_temp;
  }

  string des_enc_func(string message, string key) {
    return des_encrypt(message, key);
  }
  string des_dec_func(string rs, string key) { return des_decrypt(rs, key); }
};
  • KDC.cpp
#include <WinSock2.h>
#include <stdio.h>
#include <tchar.h>

#include "DES.cpp"
#pragma comment(lib, "ws2_32.lib")

string data = "";

char Key1[] = "1234567890abcdef";
char Key2[] = "fedcba0987654321";
char Keys[] = "fed0987654321cba";

int _tmain(int argc, _TCHAR *argv[])

{
  des machine;

  WSADATA wsaData;

  int port = 5099;

  char buf[] = "服务器: 欢迎登录......\n";

  // 加载套接字

  if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)

  {
    printf("加载套接字失败:%d......\n", WSAGetLastError());

    return 1;
  }

  // socket()

  SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, 0);

  // 初始化IP和端口信息

  SOCKADDR_IN addrSrv;

  addrSrv.sin_family = AF_INET;

  addrSrv.sin_port = htons(port);  // 1024以上的端口号

  addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);

  // bind()

  if (bind(sockSrv, (LPSOCKADDR)&addrSrv, sizeof(SOCKADDR_IN)) == SOCKET_ERROR)

  {
    printf("套接字绑定失败:%d......\n", WSAGetLastError());

    return 1;
  }

  // listen()

  if (listen(sockSrv, 10) == SOCKET_ERROR) {
    printf("套接字监听失败:%d......\n", WSAGetLastError());

    return 1;
  }

  // 客户端信息

  SOCKADDR_IN addrClient;

  int len = sizeof(SOCKADDR);

  // 开始监听

  printf("服务端启动成功......开始监听...\n");

  while (1)

  {
    // 等待客户请求到来

    SOCKET sockConn = accept(sockSrv, (SOCKADDR *)&addrClient, &len);

    if (sockConn == SOCKET_ERROR) {
      printf("建立连接失败:%d......\n", WSAGetLastError());

      break;
    }

    printf("与客户端建立连接......IP:[%s]\n", inet_ntoa(addrClient.sin_addr));

    char recvBuf[103];

    memset(recvBuf, 0, sizeof(recvBuf));

    // 接收数据

    recv(sockConn, recvBuf, sizeof(recvBuf), 0);

    printf("收到数据:%s\n", recvBuf);

    memset(recvBuf, 0, sizeof(recvBuf));

    int l1 = recv(sockConn, recvBuf, sizeof(recvBuf), 0);
    cout << "recvbuf = ";
    data = "";
    for (int i = 0; i < l1; i++) {
      cout << recvBuf[i];
      data += recvBuf[i];
    }

    cout << endl << "data = " << data << endl;
    // str1 ==> Ek1(Ks || ID1 || ID2 || N1 || Ek2( Ks || ID1 ))
    // str2 ==>Ek2( Ks || ID1 )
    // t1 ==> ID2 || N1
    // t2 ==> ID1
    // t = t_ = Ks(之后与t1,t2联合成为str1,str2加密前的信息串)
    string str1 = "";

    string str2 = "";

    string t1 = "";

    string t2 = "";

    string t = "";

    string t_ = "";

    t = Keys;

    t_ = Keys;

    t1 = data.substr(4, data.length());

    for (int i = 0; i < 4; i++) {
      t2 += data[i];
    }

    t = t + t1;

    t_ = t_ + t2;

    str2 = machine.des_enc_func(t_, Key2);

    cout << "str2 = " << str2 << endl;

    t = t + str2;

    str1 = machine.des_enc_func(t, Key1);
    // char* <-- string 的转换,为消息的发送做准备
    char buf[2003];
    int l = str1.length();
    for (int i = 0; i < l; i++) {
      buf[i] = str1[i];
    }
    if (send(sockConn, buf, l, 0) == SOCKET_ERROR) {
      printf("发送数据失败......\n");

      break;
    }

    closesocket(sockConn);
  }

  // 关闭套接字

  closesocket(sockSrv);

  WSACleanup();

  system("pause");

  return 0;
}
  • User1.cpp
#include <WinSock2.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/timeb.h>
#include <tchar.h>

#include <cstring>

#include "DES.cpp"

#pragma comment(lib, "ws2_32.lib")

string key = "1234567890abcdef";

string ks = "";

string send_t2;

int _tmain(int argc, _TCHAR *argv[])

{
  des machine;

  WSADATA wsaData;

  int port = 5099;

  char buff[2003];

  char buff1[2003];

  memset(buff, 0, sizeof(buff));

  // 加载套接字

  if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)

  {
    printf("加载套接字失败:%d......\n", WSAGetLastError());

    return 1;
  }

  // 初始化IP和端口信息

  SOCKADDR_IN addrSrv;

  addrSrv.sin_family = AF_INET;

  addrSrv.sin_port = htons(port);

  addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");

  // socket()

  SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0);

  if (SOCKET_ERROR == sockClient) {
    printf("创建套接字失败:%d......\n", WSAGetLastError());

    return 1;
  }

  // 向服务器发出连接请求

  if (connect(sockClient, (struct sockaddr *)&addrSrv, sizeof(addrSrv)) ==
      INVALID_SOCKET)

  {
    printf("连接服务器失败:%d......\n", WSAGetLastError());

    return 1;
  }

  else

  {
    // 发送数据

    char buf[] = "客户端:请求登录......";

    send(sockClient, buf, sizeof(buf), 0);

    system("pause");

    //向KDC发送请求
    char buffer[] = "00010010";
    //时间戳部分
    unsigned int time;

    timeb t;

    ftime(&t);

    time = t.time * 1000 + t.millitm;

    char timeStamp[10];

    itoa(time, timeStamp, 10);

    strcat(buffer, timeStamp);

    send(sockClient, buffer, sizeof(buffer) + sizeof(timeStamp), 0);

    // 接收KDC数据
    int len_ = 0;

    while (1) {
      len_ = recv(sockClient, buff, sizeof(buff), 0);

      if (len_ > 0) {
        break;
      }
    }

    printf("收到数据:%s\n", buff);

    string str1;

    for (int i = 0; i < len_; i++) {
      str1 += buff[i];
    }

    //解密KDC数据,得到Ks||ID1||ID2||N1||Ek2(Ks||ID1)
    //分析得Ks

    string send_t1 = machine.des_dec_func(str1, key);

    send_t2 = send_t1.substr(31, send_t1.length());

    ks = send_t1.substr(0, 16);

    cout << "send_t2 = " << send_t2 << endl;

    cout << "ks = " << ks << endl;
  }

  // 关闭套接字
  closesocket(sockClient);

  //向User2发送请求
  des machine1;

  WSADATA wsaData1;

  port = 6713;

  memset(buff, 0, sizeof(buff));

  if (WSAStartup(MAKEWORD(2, 2), &wsaData1) != 0)

  {
    printf("加载套接字失败:%d......\n", WSAGetLastError());

    return 1;
  }

  // 初始化IP和端口信息

  SOCKADDR_IN addrSrv1;

  addrSrv1.sin_family = AF_INET;

  addrSrv1.sin_port = htons(port);

  addrSrv1.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");

  // socket()

  SOCKET sockClient1 = socket(AF_INET, SOCK_STREAM, 0);

  if (SOCKET_ERROR == sockClient1) {
    printf("创建套接字失败:%d......\n", WSAGetLastError());

    return 1;
  }

  if (connect(sockClient1, (struct sockaddr *)&addrSrv1, sizeof(addrSrv1)) ==
      INVALID_SOCKET)

  {
    printf("连接服务器失败:%d......\n", WSAGetLastError());

    return 1;
  } else

  {
    // 建立连接,给User2发送数据,即KDC发来的消息中,我们无法解密的部分Ek2(Ks||ID1)

    char buf1[] = "User1:请求连接......";

    send(sockClient1, buf1, sizeof(buf1), 0);

    system("pause");

    char buffer1[301];

    int l_ = send_t2.length();

    cout << "发送消息的长度是:" << l_ << endl;

    for (int i = 0; i < l_; i++) {
      buffer1[i] = send_t2[i];
    }

    send(sockClient1, buffer1, l_, 0);

    //接收来自User2的加密信息EkS(N2)

    int len = 0;

    while (1) {
      len = recv(sockClient1, buff1, sizeof(buff1), 0);
      if (len > 0) {
        break;
      }
    }

    printf("收到数据:%s\n", buff1);

    string str3 = "";

    for (int i = 0; i < len; i++) {
      str3 += buff1[i];
    }

    cout << "str3 = " << str3 << endl;
    //对消息利用Ks进行解密,类型转化
    string str4 = machine1.des_dec_func(str3, ks);

    cout << "str4 = " << str4 << endl;

    char temp1[5];

    int l3 = str4.length();

    for (int i = 0; i < l3; i++) {
      temp1[i] = str4[i];
    }

    int n2 = atoi(temp1);
    //对随机数解密结果进行作用,期间转化数字,字符串,char*类型不停转化
    cout << "n2 = " << n2 << endl;

    char temp2[5];

    n2 += 1;

    itoa(n2, temp2, 10);

    int l2_ = sizeof(temp2);

    string str5 = "";

    for (int i = 0; i < l2_; i++) {
      str5 += temp2[i];
    }
    //转为字符串之后,利用Ks进行加密
    cout << "str5 = " << str5 << endl;

    string str6 = machine1.des_enc_func(str5, ks);

    cout << "str6 = " << str6 << endl;

    char buffer2[301];

    int l1_ = str6.length();

    for (int i = 0; i < l1_; i++) {
      buffer2[i] = str6[i];
    }
    //发送给K2
    send(sockClient1, buffer2, l1_, 0);
  }

  closesocket(sockClient1);

  WSACleanup();

  return 0;
}
  • User2.cpp
#include <WinSock2.h>
#include <stdio.h>
#include <stdlib.h>
#include <tchar.h>
#include <time.h>

#include "DES.cpp"

#pragma comment(lib, "ws2_32.lib")

using namespace std;

string key = "fedcba0987654321";

string ks = "";

string data = "";

int _tmain(int argc, _TCHAR *argv[])

{
  des machine;

  WSADATA wsaData;

  int port = 6713;

  char buf[] = "服务器: 欢迎登录......\n";

  // 加载套接字

  if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)

  {
    printf("加载套接字失败:%d......\n", WSAGetLastError());

    return 1;
  }

  // socket()

  SOCKET sockSrv = socket(AF_INET, SOCK_STREAM, 0);

  // 初始化IP和端口信息

  SOCKADDR_IN addrSrv;

  addrSrv.sin_family = AF_INET;

  addrSrv.sin_port = htons(port);  // 1024以上的端口号

  addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);

  // bind()

  if (bind(sockSrv, (LPSOCKADDR)&addrSrv, sizeof(SOCKADDR_IN)) == SOCKET_ERROR)

  {
    printf("套接字绑定失败:%d......\n", WSAGetLastError());

    return 1;
  }

  // listen()

  if (listen(sockSrv, 10) == SOCKET_ERROR) {
    printf("套接字监听失败:%d......\n", WSAGetLastError());

    return 1;
  }

  // 客户端信息

  SOCKADDR_IN addrClient;

  int len = sizeof(SOCKADDR);

  // 开始监听

  printf("服务端启动成功......开始监听...\n");

  while (1)

  {
    // 等待客户请求到来

    SOCKET sockConn = accept(sockSrv, (SOCKADDR *)&addrClient, &len);

    if (sockConn == SOCKET_ERROR) {
      printf("建立连接失败:%d......\n", WSAGetLastError());

      break;
    }

    printf("与客户端建立连接......IP:[%s]\n", inet_ntoa(addrClient.sin_addr));

    // 发送数据

    char recvBuf[601];

    memset(recvBuf, 0, sizeof(recvBuf));

    // 接收连接建立数据

    recv(sockConn, recvBuf, sizeof(recvBuf), 0);

    printf("收到数据:%s\n", recvBuf);

    memset(recvBuf, 0, sizeof(recvBuf));

    // 接收User1发来的,由KDC提供的,用KB加密的,包含Ks的数据,并对其进行解密,获得Ks

    int l1 = recv(sockConn, recvBuf, sizeof(recvBuf), 0);

    cout << "l1 = " << l1 << endl;

    data = "";

    for (int i = 0; i < l1; i++) {
      data += recvBuf[i];
    }

    cout << endl << "data = " << data << endl;

    string send_t1 = machine.des_dec_func(data, key);

    ks = send_t1.substr(0, 16);
    //生成随机数
    srand((unsigned)time(NULL));

    int a = 1, b = 10000;

    int n2 = (rand() % (b - a)) + a;

    char n_s[5];

    itoa(n2, n_s, 10);

    string send_n_t = "";

    cout << "n2 = " << n2 << endl;

    for (int i = 0; i < 5; i++) {
      send_n_t += n_s[i];
    }
    //将随机数转成字符串后使用Ks进行加密
    string send_m = machine.des_enc_func(send_n_t, ks);

    cout << "send_m = " << send_m << endl;

    char buf1[203];

    memset(buf1, 0, sizeof(buf1));

    int l = send_m.length();

    for (int i = 0; i < l; i++) {
      buf1[i] = send_m[i];
    }

    //发送给User1
    if (send(sockConn, buf1, l, 0) == SOCKET_ERROR) {
      printf("发送数据失败......\n");

      break;
    }

    cout << "l = " << l << endl;

    memset(recvBuf, 0, sizeof(recvBuf));

    int l2 = 0;
    //等待User1的返回结果
    while (1) {
      l2 = recv(sockConn, recvBuf, sizeof(recvBuf), 0);

      if (l2 > 0) {
        break;
      }
    }

    cout << "recvbuf = ";

    data = "";

    for (int i = 0; i < l2; i++) {
      data += recvBuf[i];

      cout << recvBuf[i];
    }

    cout << endl << "data = " << data << endl;
    //使用Ks进行解密,并对结果进行验证
    string str3 = machine.des_dec_func(data, ks);

    char buffer2[5];

    int l1_ = str3.length();

    for (int i = 0; i < l1_; i++) {
      buffer2[i] = str3[i];
    }

    int n3 = atoi(buffer2);

    if (n3 - n2 == 1) {
      cout << "n3 = " << n3 << " = " << n2 << " + 1,验证成功!\n";

      cout << "交换密钥:" << ks << endl;
    } else {
      cout << "验证失败!" << endl;
    }

    closesocket(sockConn);
  }

  // 关闭套接字

  closesocket(sockSrv);

  WSACleanup();

  return 0;
}

windows终端出现乱码时:使用chcp 65001命令

g++WinSock编译命令:g++ XXXX.cpp -o XXXX -lwsock32

关于网络编程,还有其他的规定,暂不赘述。

项目时长:2*7h

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值