Skip to content

Instantly share code, notes, and snippets.

@hirosof
Created February 11, 2011 17:02
Show Gist options
  • Save hirosof/822665 to your computer and use it in GitHub Desktop.
Save hirosof/822665 to your computer and use it in GitHub Desktop.
Title:Twitter OAuth認証サポート関数定義
/*
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