Created
February 11, 2011 17:02
-
-
Save hirosof/822665 to your computer and use it in GitHub Desktop.
Title:Twitter OAuth認証サポート関数定義
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Title:Twitter OAuth認証サポート関数定義 | |
作成者:Hiroaki Software | |
機能リスト | |
1.SHA1 | |
2.HMAC-SHA1 | |
3.base64エンコード | |
4.base64デコード | |
*/ | |
//インクルード | |
#include <stdio.h> | |
#include <string.h> | |
#include <malloc.h> | |
#ifndef __Twitter_OAuth_Support_Function_Definition__ | |
#define __Twitter_OAuth_Support_Function_Definition__ | |
//型定義 | |
typedef unsigned __int32 SHA_INT_TYPE; | |
//構造体定義 | |
typedef struct tagSHA1_DATA{ | |
SHA_INT_TYPE Value[5]; | |
char Val_String[45]; | |
}SHA1_DATA; | |
//メッセージダイジェストの初期値 | |
const SHA_INT_TYPE SHA1_H_Val[] = { 0x67452301 , 0xefcdab89 , 0x98badcfe , 0x10325476 , 0xc3d2e1f0 }; | |
//base64で使用する文字の配列 | |
const char base64_ChangeCharSet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | |
//プロトタイプ宣言 | |
bool HMAC_SHA1(SHA1_DATA *,const char*,const char*,SHA_INT_TYPE); | |
bool SHA1(SHA1_DATA *, const char* , SHA_INT_TYPE); | |
unsigned int base64_encode(char *,char *); | |
unsigned int base64_decode(char *,char *); | |
unsigned int urlencode(char *,char *); | |
unsigned int urldecode(char *,char *); | |
SHA_INT_TYPE SHA1_K(SHA_INT_TYPE); | |
SHA_INT_TYPE SHA1_f(SHA_INT_TYPE,SHA_INT_TYPE,SHA_INT_TYPE,SHA_INT_TYPE); | |
SHA_INT_TYPE SHA1_rotl(SHA_INT_TYPE,SHA_INT_TYPE); | |
void SHA_Reverse_INT64(const unsigned char *,unsigned __int64); | |
SHA_INT_TYPE SHA_Reverse(SHA_INT_TYPE); | |
void SHA1_HashBlock(SHA_INT_TYPE *,const unsigned char *); | |
void HMAC_SHA1_Copy(const unsigned char*,SHA1_DATA*); | |
void base64_DecToBin_8(unsigned __int8,char *); | |
void base64_Reverse_8(char *); | |
void base64_DecToBin_6(unsigned __int8,char *); | |
void base64_Reverse_6(char *); | |
int base64_BinToDec_8(char *); | |
int base64_BinToDec_6(char *); | |
unsigned char HexToChar_2b(char*); | |
bool isNeedPersentEncChar(const char); | |
//基本関数 | |
SHA_INT_TYPE SHA1_K(SHA_INT_TYPE t){ | |
if(t<=19)return 0x5a827999; | |
else if(t<=39)return 0x6ed9eba1; | |
else if(t<=59)return 0x8f1bbcdc; | |
else if(t<=79)return 0xca62c1d6; | |
return 0; | |
} | |
SHA_INT_TYPE SHA1_f(SHA_INT_TYPE t,SHA_INT_TYPE B,SHA_INT_TYPE C, SHA_INT_TYPE D){ | |
if(t<=19)return (B&C)|(~B&D); | |
else if(t<=39)return B^C^D; | |
else if(t<=59)return (B&C)|(B&D)|(C&D); | |
else if(t<=79)return B^C^D; | |
return 0; | |
} | |
//左ローテート関数 | |
SHA_INT_TYPE SHA1_rotl(SHA_INT_TYPE r,SHA_INT_TYPE x){ | |
SHA_INT_TYPE rot = r%32; | |
return (x >> (32 - rot)) | (x << rot); | |
} | |
void SHA_Reverse_INT64(unsigned char *data,unsigned __int64 write){ | |
unsigned char cdata[8]; | |
memcpy(cdata,&write,sizeof(__int64)); | |
for(int i=0;i<=7;i++)*(data + i) = cdata[7-i]; | |
} | |
SHA_INT_TYPE SHA_Reverse(SHA_INT_TYPE d){ | |
unsigned char b_data[4],a_data[4]; | |
SHA_INT_TYPE ret; | |
memcpy(b_data,&d,sizeof(__int32)); | |
for(int i=0;i<4;i++)a_data[i] = b_data[3-i]; | |
memcpy(&ret,a_data,sizeof(a_data)); | |
return ret; | |
} | |
void HMAC_SHA1_Copy(unsigned char *copy,SHA1_DATA *shd){ | |
SHA_INT_TYPE Value[5]; | |
for(int i=0;i<5;i++)Value[i] = SHA_Reverse(shd->Value[i]); | |
memcpy(copy,Value,20); | |
} | |
void SHA1_HashBlock(SHA_INT_TYPE *SHA1_H_Data , const unsigned char *data){ | |
SHA_INT_TYPE SIT[80]; | |
SHA_INT_TYPE SIT_d[16] ;//512ビット、64バイト | |
SHA_INT_TYPE a,b,c,d,e; | |
for(int i=0,j=0;i<16;i++,j+=4)SIT_d[i] = ((*(data + j +3)&0xFF) << 24)|((*(data + j + 2)&0xFF) << 16)|((*(data + j + 1)&0xFF) << 8)|((*(data + j)&0xFF)); | |
for(int i=0;i<16;i++)SIT[i] = SHA_Reverse(SIT_d[i]); | |
for(int t=16;t<=79;t++)SIT[t] = SHA1_rotl(1,SIT[t-3]^SIT[t-8]^SIT[t-14]^SIT[t-16]); | |
a = *SHA1_H_Data; | |
b = *(SHA1_H_Data + 1); | |
c = *(SHA1_H_Data + 2); | |
d = *(SHA1_H_Data + 3); | |
e = *(SHA1_H_Data + 4); | |
for(int t=0;t<=79;t++){ | |
SHA_INT_TYPE tmp; | |
tmp = SHA1_rotl(5,a)+SHA1_f(t,b,c,d)+e+SIT[t]+SHA1_K(t); | |
e = d; | |
d = c; | |
c = SHA1_rotl(30,b); | |
b=a; | |
a=tmp; | |
} | |
*SHA1_H_Data += a; | |
*(SHA1_H_Data+1)+=b; | |
*(SHA1_H_Data+2)+=c; | |
*(SHA1_H_Data+3)+=d; | |
*(SHA1_H_Data+4)+=e; | |
} | |
bool SHA1(SHA1_DATA *sha1d, const char *data , SHA_INT_TYPE size){ | |
SHA_INT_TYPE s,h[5],ns; | |
int cnt=0; | |
unsigned __int64 s64; | |
unsigned char d[64]; | |
if(!sha1d)return false; | |
s = (size)?size:strlen(data); | |
memcpy(h,SHA1_H_Val,sizeof(SHA1_H_Val)); | |
//dataのバイト数が64バイトを超えていたら60バイト未満になるまで処理をする | |
for(SHA_INT_TYPE i=s,j=0;i>=64;i-=64,j+=64)SHA1_HashBlock(h,(const unsigned char*)(data + j)); | |
//パディングに含めるデータのサイズ | |
ns = s%64; | |
//d・・・パディング文字列 | |
memset(d,0,64); | |
//パディングにコピー | |
memcpy(d,data + (s-ns),ns); | |
//d[s]に0x80を代入 | |
d[ns] = 0x80; | |
//パディングに含めるデータのサイズが56バイト以上だった時の処理 | |
if(ns >= 56){ | |
//パディングに含めるデータのサイズが56バイト以上だったらSHA1_HashBlockを実行する | |
SHA1_HashBlock(h,d); | |
//dの最初~56バイト文NULL文字をセット | |
memset(d,0,56); | |
} | |
//データのサイズをビット数にする | |
s64 = s*8; | |
//データのサイズ(ビット単位)を書き込む | |
SHA_Reverse_INT64(&d[56],s64); | |
//最後の処理 | |
SHA1_HashBlock(h,d); | |
memcpy(sha1d->Value,h,sizeof(h)); | |
sprintf(sha1d->Val_String,"%08X %08X %08X %08X %08X",h[0],h[1],h[2],h[3],h[4]); | |
return true; | |
} | |
bool HMAC_SHA1(SHA1_DATA *sha1d,const char *b_target,const char *b_key,SHA_INT_TYPE tsize){ | |
unsigned char key[65],ipad[64],opad[64]; | |
unsigned char *tk,tk2[20],tk3[84]; | |
SHA_INT_TYPE tks; | |
SHA1_DATA SD,ret; | |
memset(&SD,0,sizeof(SHA1_DATA)); | |
memset(key,0,65); | |
memset(ipad,0x36,64); | |
memset(opad,0x5c,64); | |
if(!sha1d)return false; | |
if(strlen(b_key) > 64){ | |
SHA1(&SD,b_key,0); | |
HMAC_SHA1_Copy(key,&SD); | |
}else{ | |
memcpy(key,(unsigned char*)b_key,strlen(b_key)); | |
} | |
memset(&SD,0,sizeof(SHA1_DATA)); | |
for(int i=0;i<64;i++){ | |
ipad[i] = key[i] ^ ipad[i]; | |
opad[i] = key[i] ^ opad[i]; | |
} | |
tks = (tsize)?tsize:strlen(b_target) + 64; | |
tk = (unsigned char *)malloc(tks); | |
if(!tk)return false; | |
memset(tk,0,tks); | |
memcpy(tk,ipad,64); | |
memcpy(tk+64,(unsigned char*)b_target,(tsize)?tsize:strlen(b_target)); | |
SHA1(&SD,(char *)tk,tks); | |
HMAC_SHA1_Copy(tk2,&SD); | |
memcpy(tk3,opad,64); | |
memcpy(tk3 + 64 , tk2,20); | |
SHA1(&ret,(char *)tk3,84); | |
memcpy(sha1d,&ret,sizeof(SHA1_DATA)); | |
free(tk); | |
return true; | |
} | |
void base64_Reverse_8(char *txt){ | |
char b_txt[8]; | |
//txt ⇒ b_txt | |
for(int i=0;i<8;i++)b_txt[i]=*(txt + i); | |
//b_txt ⇒ txt | |
for(int i=0;i<8;i++)*(txt + i) = b_txt[7-i]; | |
} | |
void base64_Reverse_6(char *txt){ | |
char b_txt[6]; | |
//txt ⇒ b_txt | |
for(int i=0;i<6;i++)b_txt[i]=*(txt + i); | |
//b_txt ⇒ txt | |
for(int i=0;i<6;i++)*(txt + i) = b_txt[5-i]; | |
} | |
void base64_DecToBin_8(unsigned __int8 in,char *out){ | |
char b_bin[9]; | |
unsigned __int8 b_in; | |
memset(b_bin,0,9); | |
b_in = in; | |
while(1){ | |
sprintf(b_bin,"%s%d",b_bin,b_in%2); | |
b_in/=2; | |
if(!b_in)break; | |
} | |
memcpy(out,b_bin,strlen(b_bin)); | |
memset(out + strlen(b_bin),'0',8-strlen(b_bin)); | |
base64_Reverse_8(out); | |
} | |
void base64_DecToBin_6(unsigned __int8 in,char *out){ | |
char b_bin[7]; | |
unsigned __int8 b_in; | |
memset(b_bin,0,7); | |
b_in = in; | |
while(1){ | |
sprintf(b_bin,"%s%d",b_bin,b_in%2); | |
b_in/=2; | |
if(!b_in)break; | |
} | |
memcpy(out,b_bin,strlen(b_bin)); | |
memset(out + strlen(b_bin),'0',6-strlen(b_bin)); | |
base64_Reverse_6(out); | |
} | |
int base64_BinToDec_8(char *in){ | |
int d = 128,dec=0; | |
for(int i=0;i<8;i++){ | |
if(*(in + i) == '1')dec+=d; | |
d/=2; | |
} | |
return dec; | |
} | |
int base64_BinToDec_6(char *in){ | |
int d = 32,dec=0; | |
for(int i=0;i<6;i++){ | |
if(*(in + i) == '1')dec+=d; | |
d/=2; | |
} | |
return dec; | |
} | |
unsigned int base64_encode(char *in,char *out){ | |
char *jisstring,*binstring,*retstring; | |
unsigned int retsize,binsize,jissize,push0=0,pushchar=0; | |
//各種サイズの計算 | |
jissize = strlen(in); | |
binsize = jissize * 8; | |
if(binsize%6)binsize += push0 = 6-binsize%6; | |
retsize = binsize/6; | |
if(retsize%4)retsize += pushchar = 4-retsize%4; | |
if(!out)return retsize + 1; | |
//各種メモリ管理 | |
jisstring = (char *)malloc(jissize + 1); | |
binstring = (char *)malloc(binsize + 1); | |
retstring = (char *)malloc(retsize + 1); | |
//各種初期化 | |
memset(jisstring,0,jissize + 1); | |
memset(binstring,0,binsize + 1); | |
memset(retstring,0,retsize + 1); | |
//copy | |
memcpy(jisstring,in,strlen(in)); | |
//JISコード or Shift-JIS ⇒2進数 | |
for(int i=0;i<jissize;i++)base64_DecToBin_8(*(jisstring+i),binstring + (8*i)); | |
//'0'を挿入 | |
memset(binstring + strlen(binstring),'0',push0); | |
//2進数⇒base64 | |
for(int i=0;i<binsize/6;i++){ | |
int id; | |
id = base64_BinToDec_6(binstring + (6*i)); | |
*(retstring + i) = base64_ChangeCharSet[id]; | |
} | |
//'='を挿入 | |
memset(retstring + strlen(retstring),'=',pushchar); | |
//結果をコピー | |
memcpy(out,retstring,retsize); | |
//各種解放 | |
free(jisstring); | |
free(binstring); | |
free(retstring); | |
return retsize; | |
} | |
unsigned int base64_decode(char *in,char *out){ | |
char *b64string,*binstring,*retstring; | |
unsigned int b64_size,binsize_b64,binsize,retsize; | |
unsigned int equalnum=0; | |
//各種計算 | |
//最後の=の数の計算 | |
for(int i=0;i<3;i++){ | |
if(*(in + strlen(in) - 1 - i) != '=')break; | |
equalnum++; | |
} | |
b64_size = strlen(in) - equalnum; | |
binsize_b64 = b64_size*6; | |
binsize = binsize_b64 - binsize_b64%8; | |
retsize = binsize/8; | |
if(!out)return retsize + 1; | |
//各種メモリ確保 | |
b64string = (char *)malloc(b64_size + 1); | |
binstring = (char *)malloc(binsize_b64 + 1); | |
retstring = (char *)malloc(retsize + 1); | |
//各種初期化 | |
memset(b64string,0,b64_size + 1); | |
memset(binstring,0,binsize_b64 + 1); | |
memset(retstring,0,retsize + 1); | |
//Base64をコピー | |
memcpy(b64string,in,b64_size); | |
//Base64 ⇒ 2進数 | |
for(int i=0;i<b64_size;i++){ | |
unsigned __int8 dec=0; | |
for(int j=0;j<64;j++){ | |
if(base64_ChangeCharSet[j] == *(b64string + i)){ | |
dec = j; | |
break; | |
} | |
} | |
base64_DecToBin_6(dec,binstring + i*6); | |
} | |
//2進数⇒Shift-JIS | |
for(int i=0;i<retsize;i++){ | |
*(retstring + i) = base64_BinToDec_8(binstring + i*8); | |
} | |
//コピー | |
memcpy(out,retstring,retsize); | |
//各種解放 | |
free(b64string); | |
free(binstring); | |
free(retstring); | |
return retsize; | |
} | |
//%エンコードが必要かどうかを確かめる関数 | |
bool isNeedPersentEncChar(const char ic){ | |
unsigned char c; | |
c = (unsigned char)ic; | |
if((c == 0x2E)||(c == 0x2D)||(c == 0x5F)||(c==0x20))return false; | |
else if((c>='A')&&(c<='Z'))return false; | |
else if((c>='a')&&(c<='z'))return false; | |
else if((c>='0')&&(c<='9'))return false; | |
else return true; | |
} | |
//%XX のXXのところを10進数に直す関数 | |
unsigned char HexToChar_2b(char *in){ | |
unsigned char out=0,*t; | |
//1バイト目 | |
t = (unsigned char*)in; | |
if((*t>='0')&&(*t<='9'))out = 16 * (9-((unsigned char)'9'-*t)); | |
else if((*t>='A')&&(*t<='F')) out = 16 * (15-((unsigned char)'F'-*t)); | |
else if((*t>='a')&&(*t<='f')) out = 16 * (15-((unsigned char)'f'-*t)); | |
//2バイト目 | |
t++; | |
if((*t>='0')&&(*t<='9'))out += (9-((unsigned char)'9'-*t)); | |
else if((*t>='A')&&(*t<='F')) out += (15-((unsigned char)'F'-*t)); | |
else if((*t>='a')&&(*t<='f')) out += (15-((unsigned char)'f'-*t)); | |
return out; | |
} | |
//URLエンコード | |
unsigned int urlencode(char *in,char *out){ | |
unsigned int size,pos; | |
char *enc; | |
//必要なサイズを計算 | |
size = 0; | |
for(unsigned int i= 0;i<strlen(in);i++){ | |
if(isNeedPersentEncChar(*(in + i)))size+=3; | |
else size++; | |
} | |
if(!out)return size + 1; | |
enc = (char*)malloc(size + 1); | |
memset(enc,0,size + 1); | |
pos=0; | |
for(unsigned int i= 0;i<strlen(in);i++){ | |
if(isNeedPersentEncChar(*(in + i))){ | |
sprintf(enc + pos , "%%%02x" , (unsigned char)*(in + i)); | |
pos+=3; | |
}else{ | |
if(*(in + i)==' ')*(enc + pos) = '+'; | |
else *(enc + pos)=*(in + i); | |
pos++; | |
} | |
} | |
memcpy(out,enc,size); | |
free(enc); | |
return size; | |
} | |
//URLデコード | |
unsigned int urldecode(char *in,char *out){ | |
unsigned int size,pos; | |
char *dec; | |
//必要なサイズを計算 | |
size=0; | |
for(int i=0;i<strlen(in);i++){ | |
if(*(in + i) == '%')i+=2; | |
size++; | |
} | |
if(!out)return size+1; | |
dec = (char*)malloc(size + 1); | |
memset(dec,0,size + 1); | |
pos=0; | |
for(int i=0;i<strlen(in);i++){ | |
if(*(in + i) == '%'){ | |
*(dec + pos) = (signed char)HexToChar_2b(in + i + 1); | |
i+=2; | |
}else if(*(in + i) == '+') { | |
*(dec + pos) = ' '; | |
}else{ | |
*(dec + pos) = *(in + i); | |
} | |
pos++; | |
} | |
memcpy(out,dec,size); | |
return size; | |
} | |
#endif /* __Twitter_OAuth_Support_Function_Definition__ */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment