Linux下用C编写WebSocet服务以响应HTML5的WebSocket请求

xiaoxiao2021-02-28  139

转自http://blog.csdn.net/xxdddail/article/details/19070149

在HTML5中新增了WebSocket,使得通讯变得更加方便。这样一来,Web与硬件的交互除了CGI和XHR的方式外,又有了一个新的方式。那么使用WebSocket又如何与下层通信呢?看看WebSocket的相关介绍就会发现,其类似于HTTP协议的通信,但又不同于HTTP协议通信,其最终使用的是TCP通信。具体的可以参照该文WebScoket 规范 + WebSocket 协议。

我们先来看看通信的效果图

下面是实现的步骤

1.建立SOCKET监听

WebSocket也是TCP通信,所以服务端需要先建立监听,下面是实现的代码。

[cpp] view plain copy print ? /* server.c */  #include <stdio.h>  #include <stdlib.h>  #include <string.h>  #include <unistd.h>  #include <sys/socket.h>  #include <netinet/in.h>    #include "base64.h"  #include "sha1.h"  #include "intLib.h"      #define REQUEST_LEN_MAX 1024  #define DEFEULT_SERVER_PORT 8000  #define WEB_SOCKET_KEY_LEN_MAX 256  #define RESPONSE_HEADER_LEN_MAX 1024  #define LINE_MAX 256      void shakeHand(int connfd,const char *serverKey);  char * fetchSecKey(const char * buf);  char * computeAcceptKey(const char * buf);  char * analyData(const char * buf,const int bufLen);  char * packData(const char * message,unsigned long * len);  void response(const int connfd,const char * message);    int main(int argc, char *argv[])  {      struct sockaddr_in servaddr, cliaddr;      socklen_t cliaddr_len;      int listenfd, connfd;      char buf[REQUEST_LEN_MAX];      char *data;      char str[INET_ADDRSTRLEN];      char *secWebSocketKey;      int i,n;      int connected=0;//0:not connect.1:connected.      int port= DEFEULT_SERVER_PORT;        if(argc>1)        {          port=atoi(argv[1]);        }      if(port<=0||port>0xFFFF)        {          printf("Port(%d) is out of range(1-%d)\n",port,0xFFFF);          return;        }      listenfd = socket(AF_INET, SOCK_STREAM, 0);        bzero(&servaddr, sizeof(servaddr));      servaddr.sin_family = AF_INET;      servaddr.sin_addr.s_addr = htonl(INADDR_ANY);      servaddr.sin_port = htons(port);            bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));        listen(listenfd, 20);        printf("Listen %d\nAccepting connections ...\n",port);      cliaddr_len = sizeof(cliaddr);      connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len);      printf("From %s at PORT %d\n",                 inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)),                 ntohs(cliaddr.sin_port));        while (1)        {                memset(buf,0,REQUEST_LEN_MAX);          n = read(connfd, buf, REQUEST_LEN_MAX);           printf("---------------------\n");                      if(0==connected)            {              printf("read:%d\n%s\n",n,buf);              secWebSocketKey=computeAcceptKey(buf);                shakeHand(connfd,secWebSocketKey);              connected=1;              continue;            }            data=analyData(buf,n);          response(connfd,data);      }      close(connfd);  }   /* server.c */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include "base64.h" #include "sha1.h" #include "intLib.h" #define REQUEST_LEN_MAX 1024 #define DEFEULT_SERVER_PORT 8000 #define WEB_SOCKET_KEY_LEN_MAX 256 #define RESPONSE_HEADER_LEN_MAX 1024 #define LINE_MAX 256 void shakeHand(int connfd,const char *serverKey); char * fetchSecKey(const char * buf); char * computeAcceptKey(const char * buf); char * analyData(const char * buf,const int bufLen); char * packData(const char * message,unsigned long * len); void response(const int connfd,const char * message); int main(int argc, char *argv[]) { struct sockaddr_in servaddr, cliaddr; socklen_t cliaddr_len; int listenfd, connfd; char buf[REQUEST_LEN_MAX]; char *data; char str[INET_ADDRSTRLEN]; char *secWebSocketKey; int i,n; int connected=0;//0:not connect.1:connected. int port= DEFEULT_SERVER_PORT; if(argc>1) { port=atoi(argv[1]); } if(port<=0||port>0xFFFF) { printf("Port(%d) is out of range(1-%d)\n",port,0xFFFF); return; } listenfd = socket(AF_INET, SOCK_STREAM, 0); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(port); bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); listen(listenfd, 20); printf("Listen %d\nAccepting connections ...\n",port); cliaddr_len = sizeof(cliaddr); connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len); printf("From %s at PORT %d\n", inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)), ntohs(cliaddr.sin_port)); while (1) { memset(buf,0,REQUEST_LEN_MAX); n = read(connfd, buf, REQUEST_LEN_MAX); printf("---------------------\n"); if(0==connected) { printf("read:%d\n%s\n",n,buf); secWebSocketKey=computeAcceptKey(buf); shakeHand(connfd,secWebSocketKey); connected=1; continue; } data=analyData(buf,n); response(connfd,data); } close(connfd); }

2.握手

在建立监听后,网页向服务端发现WebSocket请求,这时需要先进行握手。握手时,客户端会在协议中包含一个握手的唯一Key,服务端在拿到这个Key后,需要加入一个GUID,然后进行sha1的加密,再转换成base64,最后再发回到客户端。这样就完成了一次握手。此种握手方式是针对chrome websocket 13的版本,其他版本的可能会有所不同。下面是实现的代码。

[cpp] view plain copy print ? char * fetchSecKey(const char * buf)  {    char *key;    char *keyBegin;    char *flag="Sec-WebSocket-Key: ";    int i=0, bufLen=0;      key=(char *)malloc(WEB_SOCKET_KEY_LEN_MAX);    memset(key,0, WEB_SOCKET_KEY_LEN_MAX);    if(!buf)      {        return NULL;      }       keyBegin=strstr(buf,flag);    if(!keyBegin)      {        return NULL;      }    keyBegin+=strlen(flag);      bufLen=strlen(buf);    for(i=0;i<bufLen;i++)      {        if(keyBegin[i]==0x0A||keyBegin[i]==0x0D)      {        break;      }        key[i]=keyBegin[i];      }        return key;  }    char * computeAcceptKey(const char * buf)  {    char * clientKey;    char * serverKey;     char * sha1DataTemp;    char * sha1Data;    short temp;    int i,n;    const char * GUID="258EAFA5-E914-47DA-95CA-C5AB0DC85B11";         if(!buf)      {        return NULL;      }    clientKey=(char *)malloc(LINE_MAX);    memset(clientKey,0,LINE_MAX);    clientKey=fetchSecKey(buf);       if(!clientKey)      {        return NULL;      }         strcat(clientKey,GUID);      sha1DataTemp=sha1_hash(clientKey);    n=strlen(sha1DataTemp);        sha1Data=(char *)malloc(n/2+1);    memset(sha1Data,0,n/2+1);       for(i=0;i<n;i+=2)      {              sha1Data[i/2]=htoi(sha1DataTemp,i,2);          }       serverKey = base64_encode(sha1Data, strlen(sha1Data));       return serverKey;  }    void shakeHand(int connfd,const char *serverKey)  {    char responseHeader [RESPONSE_HEADER_LEN_MAX];      if(!connfd)      {        return;      }      if(!serverKey)      {        return;      }      memset(responseHeader,'\0',RESPONSE_HEADER_LEN_MAX);      sprintf(responseHeader, "HTTP/1.1 101 Switching Protocols\r\n");    sprintf(responseHeader, "%sUpgrade: websocket\r\n", responseHeader);    sprintf(responseHeader, "%sConnection: Upgrade\r\n", responseHeader);    sprintf(responseHeader, "%sSec-WebSocket-Accept: %s\r\n\r\n", responseHeader, serverKey);       printf("Response Header:%s\n",responseHeader);      write(connfd,responseHeader,strlen(responseHeader));  }   char * fetchSecKey(const char * buf) { char *key; char *keyBegin; char *flag="Sec-WebSocket-Key: "; int i=0, bufLen=0; key=(char *)malloc(WEB_SOCKET_KEY_LEN_MAX); memset(key,0, WEB_SOCKET_KEY_LEN_MAX); if(!buf) { return NULL; } keyBegin=strstr(buf,flag); if(!keyBegin) { return NULL; } keyBegin+=strlen(flag); bufLen=strlen(buf); for(i=0;i<bufLen;i++) { if(keyBegin[i]==0x0A||keyBegin[i]==0x0D) { break; } key[i]=keyBegin[i]; } return key; } char * computeAcceptKey(const char * buf) { char * clientKey; char * serverKey; char * sha1DataTemp; char * sha1Data; short temp; int i,n; const char * GUID="258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; if(!buf) { return NULL; } clientKey=(char *)malloc(LINE_MAX); memset(clientKey,0,LINE_MAX); clientKey=fetchSecKey(buf); if(!clientKey) { return NULL; } strcat(clientKey,GUID); sha1DataTemp=sha1_hash(clientKey); n=strlen(sha1DataTemp); sha1Data=(char *)malloc(n/2+1); memset(sha1Data,0,n/2+1); for(i=0;i<n;i+=2) { sha1Data[i/2]=htoi(sha1DataTemp,i,2); } serverKey = base64_encode(sha1Data, strlen(sha1Data)); return serverKey; } void shakeHand(int connfd,const char *serverKey) { char responseHeader [RESPONSE_HEADER_LEN_MAX]; if(!connfd) { return; } if(!serverKey) { return; } memset(responseHeader,'\0',RESPONSE_HEADER_LEN_MAX); sprintf(responseHeader, "HTTP/1.1 101 Switching Protocols\r\n"); sprintf(responseHeader, "%sUpgrade: websocket\r\n", responseHeader); sprintf(responseHeader, "%sConnection: Upgrade\r\n", responseHeader); sprintf(responseHeader, "%sSec-WebSocket-Accept: %s\r\n\r\n", responseHeader, serverKey); printf("Response Header:%s\n",responseHeader); write(connfd,responseHeader,strlen(responseHeader)); } 注意:

1.Connection后面的值与HTTP通信时的不一样了,是Upgrade,而Upgrade又对应到了websocket,这样就标识了该通信协议是websocket的方式。

2.在sha1加密后进行base64编码时,使用sha1加密后的串必须将其当成16进制的字符串,将每两个字符合成一个新的码(0-0xFF间)来进一步计算后,才可以进行base64换算(我开始时就在这里折腾了很久,后面才弄明白还要加上这一步),如果是直接就base64,那就会握手失败。

3.对于sha1和base64网上有很多,后面也附上我所使用的代码。

3.数据传输

握手成功后就可以进行数据传输了,只要按照WebSocket的协议来解就可以了。下面是实现的代码

[cpp] view plain copy print ? char * analyData(const char * buf,const int bufLen)  {    char * data;    char fin, maskFlag,masks[4];    char * payloadData;    char temp[8];    unsigned long n, payloadLen=0;    unsigned short usLen=0;    int i=0;        if (bufLen < 2)      {       return NULL;     }      fin = (buf[0] & 0x80) == 0x80; // 1bit,1表示最后一帧      if (!fin)     {         return NULL;// 超过一帧暂不处理      }       maskFlag = (buf[1] & 0x80) == 0x80; // 是否包含掩码       if (!maskFlag)     {         return NULL;// 不包含掩码的暂不处理     }       payloadLen = buf[1] & 0x7F; // 数据长度      if (payloadLen == 126)     {             memcpy(masks,buf+4, 4);             payloadLen =(buf[2]&0xFF) << 8 | (buf[3]&0xFF);         payloadData=(char *)malloc(payloadLen);       memset(payloadData,0,payloadLen);       memcpy(payloadData,buf+8,payloadLen);      }      else if (payloadLen == 127)      {       memcpy(masks,buf+10,4);         for ( i = 0; i < 8; i++)       {           temp[i] = buf[9 - i];       }          memcpy(&n,temp,8);         payloadData=(char *)malloc(n);        memset(payloadData,0,n);        memcpy(payloadData,buf+14,n);//toggle error(core dumped) if data is too long.       payloadLen=n;           }       else       {           memcpy(masks,buf+2,4);            payloadData=(char *)malloc(payloadLen);        memset(payloadData,0,payloadLen);        memcpy(payloadData,buf+6,payloadLen);        }         for (i = 0; i < payloadLen; i++)       {         payloadData[i] = (char)(payloadData[i] ^ masks[i % 4]);       }          printf("data(%d):%s\n",payloadLen,payloadData);       return payloadData;  }    char *  packData(const char * message,unsigned long * len)   {           char * data=NULL;       unsigned long n;         n=strlen(message);              if (n < 126)              {            data=(char *)malloc(n+2);            memset(data,0,n+2);                data[0] = 0x81;            data[1] = n;            memcpy(data+2,message,n);            *len=n+2;              }              else if (n < 0xFFFF)              {            data=(char *)malloc(n+4);            memset(data,0,n+4);            data[0] = 0x81;            data[1] = 126;            data[2] = (n>>8 & 0xFF);            data[3] = (n & 0xFF);            memcpy(data+4,message,n);                *len=n+4;              }              else              {                         // 暂不处理超长内容              *len=0;              }                return data;   }    void response(int connfd,const char * message)  {    char * data;    unsigned long n=0;    int i;    if(!connfd)      {        return;      }      if(!data)      {        return;      }    data=packData(message,&n);        if(!data||n<=0)      {        printf("data is empty!\n");        return;      }        write(connfd,data,n);      }   char * analyData(const char * buf,const int bufLen) { char * data; char fin, maskFlag,masks[4]; char * payloadData; char temp[8]; unsigned long n, payloadLen=0; unsigned short usLen=0; int i=0; if (bufLen < 2) { return NULL; } fin = (buf[0] & 0x80) == 0x80; // 1bit,1表示最后一帧 if (!fin) { return NULL;// 超过一帧暂不处理 } maskFlag = (buf[1] & 0x80) == 0x80; // 是否包含掩码 if (!maskFlag) { return NULL;// 不包含掩码的暂不处理 } payloadLen = buf[1] & 0x7F; // 数据长度 if (payloadLen == 126) { memcpy(masks,buf+4, 4); payloadLen =(buf[2]&0xFF) << 8 | (buf[3]&0xFF); payloadData=(char *)malloc(payloadLen); memset(payloadData,0,payloadLen); memcpy(payloadData,buf+8,payloadLen); } else if (payloadLen == 127) { memcpy(masks,buf+10,4); for ( i = 0; i < 8; i++) { temp[i] = buf[9 - i]; } memcpy(&n,temp,8); payloadData=(char *)malloc(n); memset(payloadData,0,n); memcpy(payloadData,buf+14,n);//toggle error(core dumped) if data is too long. payloadLen=n; } else { memcpy(masks,buf+2,4); payloadData=(char *)malloc(payloadLen); memset(payloadData,0,payloadLen); memcpy(payloadData,buf+6,payloadLen); } for (i = 0; i < payloadLen; i++) { payloadData[i] = (char)(payloadData[i] ^ masks[i % 4]); } printf("data(%d):%s\n",payloadLen,payloadData); return payloadData; } char * packData(const char * message,unsigned long * len) { char * data=NULL; unsigned long n; n=strlen(message); if (n < 126) { data=(char *)malloc(n+2); memset(data,0,n+2); data[0] = 0x81; data[1] = n; memcpy(data+2,message,n); *len=n+2; } else if (n < 0xFFFF) { data=(char *)malloc(n+4); memset(data,0,n+4); data[0] = 0x81; data[1] = 126; data[2] = (n>>8 & 0xFF); data[3] = (n & 0xFF); memcpy(data+4,message,n); *len=n+4; } else { // 暂不处理超长内容 *len=0; } return data; } void response(int connfd,const char * message) { char * data; unsigned long n=0; int i; if(!connfd) { return; } if(!data) { return; } data=packData(message,&n); if(!data||n<=0) { printf("data is empty!\n"); return; } write(connfd,data,n); } 注意:

1.对于超过0xFFFF长度的数据在分析数据部分虽然作了处理,但是在memcpy时会报core dumped的错误,没有解决,请过路的大牛帮忙指点。在packData部分也未对这一部分作处理。

2.在这里碰到了一个郁闷的问题,在命名函数时,将函数名写的过长了(fetchSecWebSocketAcceptkey),结果导致编译通过,但在运行时却莫名其妙的报core dumped的错误,试了很多方法才发现是这个原因,后将名字改短后就OK了。

3.在回复数据时,只要按websocket的协议进行回应就可以了。

附上sha1、base64和intLib的代码(sha1和base64是从网上摘来的)

sha1.h

[cpp] view plain copy print ? //sha1.h:对字符串进行sha1加密  #ifndef _SHA1_H_  #define _SHA1_H_    #include <stdio.h>  #include <stdlib.h>  #include <string.h>      typedef struct SHA1Context{      unsigned Message_Digest[5];            unsigned Length_Low;                   unsigned Length_High;                  unsigned char Message_Block[64];       int Message_Block_Index;               int Computed;                          int Corrupted;                     } SHA1Context;    void SHA1Reset(SHA1Context *);  int SHA1Result(SHA1Context *);  void SHA1Input( SHA1Context *,const char *,unsigned);  #endif      #define SHA1CircularShift(bits,word) ((((word) << (bits)) & 0xFFFFFFFF) | ((word) >> (32-(bits))))    void SHA1ProcessMessageBlock(SHA1Context *);  void SHA1PadMessage(SHA1Context *);    void SHA1Reset(SHA1Context *context){// 初始化动作      context->Length_Low             = 0;      context->Length_High            = 0;      context->Message_Block_Index    = 0;        context->Message_Digest[0]      = 0x67452301;      context->Message_Digest[1]      = 0xEFCDAB89;      context->Message_Digest[2]      = 0x98BADCFE;      context->Message_Digest[3]      = 0x10325476;      context->Message_Digest[4]      = 0xC3D2E1F0;        context->Computed   = 0;      context->Corrupted  = 0;  }      int SHA1Result(SHA1Context *context){// 成功返回1,失败返回0      if (context->Corrupted) {          return 0;      }      if (!context->Computed) {          SHA1PadMessage(context);          context->Computed = 1;      }      return 1;  }      void SHA1Input(SHA1Context *context,const char *message_array,unsigned length){      if (!length) return;        if (context->Computed || context->Corrupted){          context->Corrupted = 1;          return;      }        while(length-- && !context->Corrupted){          context->Message_Block[context->Message_Block_Index++] = (*message_array & 0xFF);            context->Length_Low += 8;            context->Length_Low &= 0xFFFFFFFF;          if (context->Length_Low == 0){              context->Length_High++;              context->Length_High &= 0xFFFFFFFF;              if (context->Length_High == 0) context->Corrupted = 1;          }            if (context->Message_Block_Index == 64){              SHA1ProcessMessageBlock(context);          }          message_array++;      }  }    void SHA1ProcessMessageBlock(SHA1Context *context){      const unsigned K[] = {0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 };      int         t;                      unsigned    temp;                   unsigned    W[80];                  unsigned    A, B, C, D, E;            for(t = 0; t < 16; t++) {      W[t] = ((unsigned) context->Message_Block[t * 4]) << 24;      W[t] |= ((unsigned) context->Message_Block[t * 4 + 1]) << 16;      W[t] |= ((unsigned) context->Message_Block[t * 4 + 2]) << 8;      W[t] |= ((unsigned) context->Message_Block[t * 4 + 3]);      }            for(t = 16; t < 80; t++)  W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);        A = context->Message_Digest[0];      B = context->Message_Digest[1];      C = context->Message_Digest[2];      D = context->Message_Digest[3];      E = context->Message_Digest[4];        for(t = 0; t < 20; t++) {          temp =  SHA1CircularShift(5,A) + ((B & C) | ((~B) & D)) + E + W[t] + K[0];          temp &= 0xFFFFFFFF;          E = D;          D = C;          C = SHA1CircularShift(30,B);          B = A;          A = temp;      }      for(t = 20; t < 40; t++) {          temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];          temp &= 0xFFFFFFFF;          E = D;          D = C;          C = SHA1CircularShift(30,B);          B = A;          A = temp;      }      for(t = 40; t < 60; t++) {          temp = SHA1CircularShift(5,A) + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];          temp &= 0xFFFFFFFF;          E = D;          D = C;          C = SHA1CircularShift(30,B);          B = A;          A = temp;      }      for(t = 60; t < 80; t++) {          temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];          temp &= 0xFFFFFFFF;          E = D;          D = C;          C = SHA1CircularShift(30,B);          B = A;          A = temp;      }      context->Message_Digest[0] = (context->Message_Digest[0] + A) & 0xFFFFFFFF;      context->Message_Digest[1] = (context->Message_Digest[1] + B) & 0xFFFFFFFF;      context->Message_Digest[2] = (context->Message_Digest[2] + C) & 0xFFFFFFFF;      context->Message_Digest[3] = (context->Message_Digest[3] + D) & 0xFFFFFFFF;      context->Message_Digest[4] = (context->Message_Digest[4] + E) & 0xFFFFFFFF;      context->Message_Block_Index = 0;  }    void SHA1PadMessage(SHA1Context *context){      if (context->Message_Block_Index > 55) {          context->Message_Block[context->Message_Block_Index++] = 0x80;          while(context->Message_Block_Index < 64)  context->Message_Block[context->Message_Block_Index++] = 0;          SHA1ProcessMessageBlock(context);          while(context->Message_Block_Index < 56) context->Message_Block[context->Message_Block_Index++] = 0;      } else {          context->Message_Block[context->Message_Block_Index++] = 0x80;          while(context->Message_Block_Index < 56) context->Message_Block[context->Message_Block_Index++] = 0;      }      context->Message_Block[56] = (context->Length_High >> 24 ) & 0xFF;      context->Message_Block[57] = (context->Length_High >> 16 ) & 0xFF;      context->Message_Block[58] = (context->Length_High >> 8 ) & 0xFF;      context->Message_Block[59] = (context->Length_High) & 0xFF;      context->Message_Block[60] = (context->Length_Low >> 24 ) & 0xFF;      context->Message_Block[61] = (context->Length_Low >> 16 ) & 0xFF;      context->Message_Block[62] = (context->Length_Low >> 8 ) & 0xFF;      context->Message_Block[63] = (context->Length_Low) & 0xFF;        SHA1ProcessMessageBlock(context);  }    /* int sha1_hash(const char *source, char *lrvar){// Main     SHA1Context sha;     char buf[128];      SHA1Reset(&sha);     SHA1Input(&sha, source, strlen(source));      if (!SHA1Result(&sha)){         printf("SHA1 ERROR: Could not compute message digest");         return -1;     } else {         memset(buf,0,sizeof(buf));         sprintf(buf, "XXXXX", sha.Message_Digest[0],sha.Message_Digest[1],         sha.Message_Digest[2],sha.Message_Digest[3],sha.Message_Digest[4]);         //lr_save_string(buf, lrvar);                  return strlen(buf);     } } */    char * sha1_hash(const char *source){// Main      SHA1Context sha;      char *buf;//[128];        SHA1Reset(&sha);      SHA1Input(&sha, source, strlen(source));        if (!SHA1Result(&sha)){          printf("SHA1 ERROR: Could not compute message digest");          return NULL;      } else {        buf=(char *)malloc(128);          memset(buf,0,sizeof(buf));          sprintf(buf, "XXXXX", sha.Message_Digest[0],sha.Message_Digest[1],          sha.Message_Digest[2],sha.Message_Digest[3],sha.Message_Digest[4]);          //lr_save_string(buf, lrvar);                    //return strlen(buf);          return buf;      }  }   //sha1.h:对字符串进行sha1加密 #ifndef _SHA1_H_ #define _SHA1_H_ #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct SHA1Context{ unsigned Message_Digest[5]; unsigned Length_Low; unsigned Length_High; unsigned char Message_Block[64]; int Message_Block_Index; int Computed; int Corrupted; } SHA1Context; void SHA1Reset(SHA1Context *); int SHA1Result(SHA1Context *); void SHA1Input( SHA1Context *,const char *,unsigned); #endif #define SHA1CircularShift(bits,word) ((((word) << (bits)) & 0xFFFFFFFF) | ((word) >> (32-(bits)))) void SHA1ProcessMessageBlock(SHA1Context *); void SHA1PadMessage(SHA1Context *); void SHA1Reset(SHA1Context *context){// 初始化动作 context->Length_Low = 0; context->Length_High = 0; context->Message_Block_Index = 0; context->Message_Digest[0] = 0x67452301; context->Message_Digest[1] = 0xEFCDAB89; context->Message_Digest[2] = 0x98BADCFE; context->Message_Digest[3] = 0x10325476; context->Message_Digest[4] = 0xC3D2E1F0; context->Computed = 0; context->Corrupted = 0; } int SHA1Result(SHA1Context *context){// 成功返回1,失败返回0 if (context->Corrupted) { return 0; } if (!context->Computed) { SHA1PadMessage(context); context->Computed = 1; } return 1; } void SHA1Input(SHA1Context *context,const char *message_array,unsigned length){ if (!length) return; if (context->Computed || context->Corrupted){ context->Corrupted = 1; return; } while(length-- && !context->Corrupted){ context->Message_Block[context->Message_Block_Index++] = (*message_array & 0xFF); context->Length_Low += 8; context->Length_Low &= 0xFFFFFFFF; if (context->Length_Low == 0){ context->Length_High++; context->Length_High &= 0xFFFFFFFF; if (context->Length_High == 0) context->Corrupted = 1; } if (context->Message_Block_Index == 64){ SHA1ProcessMessageBlock(context); } message_array++; } } void SHA1ProcessMessageBlock(SHA1Context *context){ const unsigned K[] = {0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 }; int t; unsigned temp; unsigned W[80]; unsigned A, B, C, D, E; for(t = 0; t < 16; t++) { W[t] = ((unsigned) context->Message_Block[t * 4]) << 24; W[t] |= ((unsigned) context->Message_Block[t * 4 + 1]) << 16; W[t] |= ((unsigned) context->Message_Block[t * 4 + 2]) << 8; W[t] |= ((unsigned) context->Message_Block[t * 4 + 3]); } for(t = 16; t < 80; t++) W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); A = context->Message_Digest[0]; B = context->Message_Digest[1]; C = context->Message_Digest[2]; D = context->Message_Digest[3]; E = context->Message_Digest[4]; for(t = 0; t < 20; t++) { temp = SHA1CircularShift(5,A) + ((B & C) | ((~B) & D)) + E + W[t] + K[0]; temp &= 0xFFFFFFFF; E = D; D = C; C = SHA1CircularShift(30,B); B = A; A = temp; } for(t = 20; t < 40; t++) { temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1]; temp &= 0xFFFFFFFF; E = D; D = C; C = SHA1CircularShift(30,B); B = A; A = temp; } for(t = 40; t < 60; t++) { temp = SHA1CircularShift(5,A) + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]; temp &= 0xFFFFFFFF; E = D; D = C; C = SHA1CircularShift(30,B); B = A; A = temp; } for(t = 60; t < 80; t++) { temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3]; temp &= 0xFFFFFFFF; E = D; D = C; C = SHA1CircularShift(30,B); B = A; A = temp; } context->Message_Digest[0] = (context->Message_Digest[0] + A) & 0xFFFFFFFF; context->Message_Digest[1] = (context->Message_Digest[1] + B) & 0xFFFFFFFF; context->Message_Digest[2] = (context->Message_Digest[2] + C) & 0xFFFFFFFF; context->Message_Digest[3] = (context->Message_Digest[3] + D) & 0xFFFFFFFF; context->Message_Digest[4] = (context->Message_Digest[4] + E) & 0xFFFFFFFF; context->Message_Block_Index = 0; } void SHA1PadMessage(SHA1Context *context){ if (context->Message_Block_Index > 55) { context->Message_Block[context->Message_Block_Index++] = 0x80; while(context->Message_Block_Index < 64) context->Message_Block[context->Message_Block_Index++] = 0; SHA1ProcessMessageBlock(context); while(context->Message_Block_Index < 56) context->Message_Block[context->Message_Block_Index++] = 0; } else { context->Message_Block[context->Message_Block_Index++] = 0x80; while(context->Message_Block_Index < 56) context->Message_Block[context->Message_Block_Index++] = 0; } context->Message_Block[56] = (context->Length_High >> 24 ) & 0xFF; context->Message_Block[57] = (context->Length_High >> 16 ) & 0xFF; context->Message_Block[58] = (context->Length_High >> 8 ) & 0xFF; context->Message_Block[59] = (context->Length_High) & 0xFF; context->Message_Block[60] = (context->Length_Low >> 24 ) & 0xFF; context->Message_Block[61] = (context->Length_Low >> 16 ) & 0xFF; context->Message_Block[62] = (context->Length_Low >> 8 ) & 0xFF; context->Message_Block[63] = (context->Length_Low) & 0xFF; SHA1ProcessMessageBlock(context); } /* int sha1_hash(const char *source, char *lrvar){// Main SHA1Context sha; char buf[128]; SHA1Reset(&sha); SHA1Input(&sha, source, strlen(source)); if (!SHA1Result(&sha)){ printf("SHA1 ERROR: Could not compute message digest"); return -1; } else { memset(buf,0,sizeof(buf)); sprintf(buf, "XXXXX", sha.Message_Digest[0],sha.Message_Digest[1], sha.Message_Digest[2],sha.Message_Digest[3],sha.Message_Digest[4]); //lr_save_string(buf, lrvar); return strlen(buf); } } */ char * sha1_hash(const char *source){// Main SHA1Context sha; char *buf;//[128]; SHA1Reset(&sha); SHA1Input(&sha, source, strlen(source)); if (!SHA1Result(&sha)){ printf("SHA1 ERROR: Could not compute message digest"); return NULL; } else { buf=(char *)malloc(128); memset(buf,0,sizeof(buf)); sprintf(buf, "XXXXX", sha.Message_Digest[0],sha.Message_Digest[1], sha.Message_Digest[2],sha.Message_Digest[3],sha.Message_Digest[4]); //lr_save_string(buf, lrvar); //return strlen(buf); return buf; } } base64.h

[cpp] view plain copy print ? #ifndef _BASE64_H_  #define _BASE64_H_     #include <stdio.h>   #include <stdlib.h>  #include <string.h>    const char base[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";   char* base64_encode(const char* data, int data_len);   char *base64_decode(const char* data, int data_len);   static char find_pos(char ch);     /* */   char *base64_encode(const char* data, int data_len)   {       //int data_len = strlen(data);       int prepare = 0;       int ret_len;       int temp = 0;       char *ret = NULL;       char *f = NULL;       int tmp = 0;       char changed[4];       int i = 0;       ret_len = data_len / 3;       temp = data_len % 3;       if (temp > 0)       {           ret_len += 1;       }       ret_len = ret_len*4 + 1;       ret = (char *)malloc(ret_len);               if ( ret == NULL)       {           printf("No enough memory.\n");           exit(0);       }       memset(ret, 0, ret_len);       f = ret;       while (tmp < data_len)       {           temp = 0;           prepare = 0;           memset(changed, '\0', 4);           while (temp < 3)           {               //printf("tmp = %d\n", tmp);               if (tmp >= data_len)               {                   break;               }               prepare = ((prepare << 8) | (data[tmp] & 0xFF));               tmp++;               temp++;           }           prepare = (prepare<<((3-temp)*8));           //printf("before for : temp = %d, prepare = %d\n", temp, prepare);           for (i = 0; i < 4 ;i++ )           {               if (temp < i)               {                   changed[i] = 0x40;               }               else               {                   changed[i] = (prepare>>((3-i)*6)) & 0x3F;               }               *f = base[changed[i]];               //printf("%.2X", changed[i]);               f++;           }       }       *f = '\0';               return ret;           }   /* */   static char find_pos(char ch)     {       char *ptr = (char*)strrchr(base, ch);//the last position (the only) in base[]       return (ptr - base);   }   /* */   char *base64_decode(const char *data, int data_len)   {       int ret_len = (data_len / 4) * 3;       int equal_count = 0;       char *ret = NULL;       char *f = NULL;       int tmp = 0;       int temp = 0;       char need[3];       int prepare = 0;       int i = 0;       if (*(data + data_len - 1) == '=')       {           equal_count += 1;       }       if (*(data + data_len - 2) == '=')       {           equal_count += 1;       }       if (*(data + data_len - 3) == '=')       {//seems impossible           equal_count += 1;       }       switch (equal_count)       {       case 0:           ret_len += 4;//3 + 1 [1 for NULL]           break;       case 1:           ret_len += 4;//Ceil((6*3)/8)+1           break;       case 2:           ret_len += 3;//Ceil((6*2)/8)+1           break;       case 3:           ret_len += 2;//Ceil((6*1)/8)+1           break;       }       ret = (char *)malloc(ret_len);       if (ret == NULL)       {           printf("No enough memory.\n");           exit(0);       }       memset(ret, 0, ret_len);       f = ret;       while (tmp < (data_len - equal_count))       {           temp = 0;           prepare = 0;           memset(need, 0, 4);           while (temp < 4)           {               if (tmp >= (data_len - equal_count))               {                   break;               }               prepare = (prepare << 6) | (find_pos(data[tmp]));               temp++;               tmp++;           }           prepare = prepare << ((4-temp) * 6);           for (i=0; i<3 ;i++ )           {               if (i == temp)               {                   break;               }               *f = (char)((prepare>>((2-i)*8)) & 0xFF);               f++;           }       }       *f = '\0';       return ret;   }    #endif   #ifndef _BASE64_H_ #define _BASE64_H_ #include <stdio.h> #include <stdlib.h> #include <string.h> const char base[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; char* base64_encode(const char* data, int data_len); char *base64_decode(const char* data, int data_len); static char find_pos(char ch); /* */ char *base64_encode(const char* data, int data_len) { //int data_len = strlen(data); int prepare = 0; int ret_len; int temp = 0; char *ret = NULL; char *f = NULL; int tmp = 0; char changed[4]; int i = 0; ret_len = data_len / 3; temp = data_len % 3; if (temp > 0) { ret_len += 1; } ret_len = ret_len*4 + 1; ret = (char *)malloc(ret_len); if ( ret == NULL) { printf("No enough memory.\n"); exit(0); } memset(ret, 0, ret_len); f = ret; while (tmp < data_len) { temp = 0; prepare = 0; memset(changed, '\0', 4); while (temp < 3) { //printf("tmp = %d\n", tmp); if (tmp >= data_len) { break; } prepare = ((prepare << 8) | (data[tmp] & 0xFF)); tmp++; temp++; } prepare = (prepare<<((3-temp)*8)); //printf("before for : temp = %d, prepare = %d\n", temp, prepare); for (i = 0; i < 4 ;i++ ) { if (temp < i) { changed[i] = 0x40; } else { changed[i] = (prepare>>((3-i)*6)) & 0x3F; } *f = base[changed[i]]; //printf("%.2X", changed[i]); f++; } } *f = '\0'; return ret; } /* */ static char find_pos(char ch) { char *ptr = (char*)strrchr(base, ch);//the last position (the only) in base[] return (ptr - base); } /* */ char *base64_decode(const char *data, int data_len) { int ret_len = (data_len / 4) * 3; int equal_count = 0; char *ret = NULL; char *f = NULL; int tmp = 0; int temp = 0; char need[3]; int prepare = 0; int i = 0; if (*(data + data_len - 1) == '=') { equal_count += 1; } if (*(data + data_len - 2) == '=') { equal_count += 1; } if (*(data + data_len - 3) == '=') {//seems impossible equal_count += 1; } switch (equal_count) { case 0: ret_len += 4;//3 + 1 [1 for NULL] break; case 1: ret_len += 4;//Ceil((6*3)/8)+1 break; case 2: ret_len += 3;//Ceil((6*2)/8)+1 break; case 3: ret_len += 2;//Ceil((6*1)/8)+1 break; } ret = (char *)malloc(ret_len); if (ret == NULL) { printf("No enough memory.\n"); exit(0); } memset(ret, 0, ret_len); f = ret; while (tmp < (data_len - equal_count)) { temp = 0; prepare = 0; memset(need, 0, 4); while (temp < 4) { if (tmp >= (data_len - equal_count)) { break; } prepare = (prepare << 6) | (find_pos(data[tmp])); temp++; tmp++; } prepare = prepare << ((4-temp) * 6); for (i=0; i<3 ;i++ ) { if (i == temp) { break; } *f = (char)((prepare>>((2-i)*8)) & 0xFF); f++; } } *f = '\0'; return ret; } #endif intLib.h

[cpp] view plain copy print ? #ifndef _INT_LIB_H_  #define _INT_LIB_H_  int tolower(int c)   {       if (c >= 'A' && c <= 'Z')       {           return c + 'a' - 'A';       }       else       {           return c;       }   }     int htoi(const char s[],int start,int len)   {     int i,j;       int n = 0;       if (s[0] == '0' && (s[1]=='x' || s[1]=='X')) //判断是否有前导0x或者0X      {           i = 2;       }       else       {           i = 0;       }       i+=start;      j=0;      for (; (s[i] >= '0' && s[i] <= '9')          || (s[i] >= 'a' && s[i] <= 'f') || (s[i] >='A' && s[i] <= 'F');++i)       {             if(j>=len)      {        break;      }          if (tolower(s[i]) > '9')           {               n = 16 * n + (10 + tolower(s[i]) - 'a');           }           else           {               n = 16 * n + (tolower(s[i]) - '0');           }       j++;      }       return n;   }       #endif   #ifndef _INT_LIB_H_ #define _INT_LIB_H_ int tolower(int c) { if (c >= 'A' && c <= 'Z') { return c + 'a' - 'A'; } else { return c; } } int htoi(const char s[],int start,int len) { int i,j; int n = 0; if (s[0] == '0' && (s[1]=='x' || s[1]=='X')) //判断是否有前导0x或者0X { i = 2; } else { i = 0; } i+=start; j=0; for (; (s[i] >= '0' && s[i] <= '9') || (s[i] >= 'a' && s[i] <= 'f') || (s[i] >='A' && s[i] <= 'F');++i) { if(j>=len) { break; } if (tolower(s[i]) > '9') { n = 16 * n + (10 + tolower(s[i]) - 'a'); } else { n = 16 * n + (tolower(s[i]) - '0'); } j++; } return n; } #endif 转载请注明出处 http://blog.csdn.net/xxdddail/article/details/19070149

转载请注明原文地址: https://www.6miu.com/read-41239.html

最新回复(0)