Created
February 7, 2011 12:03
-
-
Save hirosof/814289 to your computer and use it in GitHub Desktop.
SHA1とHMAC-SHA1とSHA256とHMAC-SHA256をC++で実装
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
/* | |
--------------------------------- | |
SHA1 と HMAC-SHA1 と SHA256 と HMAC-SHA256(Win32 API未使用) | |
作成者:Hiroaki Software | |
---------------------------------- | |
-------------参考資料など----------- | |
1.Javaで作って学ぶ暗号技術 (森北出版) | |
2.暗号化アルゴリズムを実感しよう その2 | |
http://www.geocities.co.jp/SiliconValley-Oakland/8878/lab18/lab18.html | |
3.フリーのsha1ハッシュ計算ツール | |
http://tools.fictionlife.com/sha1/ | |
4.Twitter API プログラミング (ワークスコーポレーション) | |
----------------------------------- | |
*/ | |
//インクルード | |
#include <stdio.h> | |
#include <string.h> | |
#include <malloc.h> | |
//型定義 | |
typedef unsigned __int32 SHA_INT_TYPE; | |
//構造体定義 | |
typedef struct tagSHA256_DATA{ | |
SHA_INT_TYPE Value[8]; | |
char Val_String[72]; | |
}SHA256_DATA; | |
typedef struct tagSHA1_DATA{ | |
SHA_INT_TYPE Value[5]; | |
char Val_String[45]; | |
}SHA1_DATA; | |
//SHA1のメッセージダイジェスト初期値 | |
const SHA_INT_TYPE SHA1_H_Val[] = { 0x67452301 , 0xefcdab89 , 0x98badcfe , 0x10325476 , 0xc3d2e1f0 }; | |
//SHA256のメッセージダイジェスト初期値 | |
const SHA_INT_TYPE SHA256_H_Val[] = { 0x6a09e667 , 0xbb67ae85 , 0x3c6ef372 , 0xa54ff53a , 0x510e527f , 0x9b05688c , 0x1f83d9ab , 0x5be0cd19 } ; | |
//SHA256の加算定数 | |
const SHA_INT_TYPE SHA256_K_Val[] = { 0x428a2f98 , 0x71374491 , 0xb5c0fbcf , 0xe9b5dba5 , 0x3956c25b , 0x59f111f1 , 0x923f82a4 , 0xab1c5ed5 , | |
0xd807aa98 , 0x12835b01 , 0x243185be , 0x550c7dc3 , 0x72be5d74 , 0x80deb1fe , 0x9bdc06a7 , 0xc19bf174 , | |
0xe49b69c1 , 0xefbe4786 , 0x0fc19dc6 , 0x240ca1cc , 0x2de92c6f , 0x4a7484aa , 0x5cb0a9dc , 0x76f988da , | |
0x983e5152 , 0xa831c66d , 0xb00327c8 , 0xbf597fc7 , 0xc6e00bf3 , 0xd5a79147 , 0x06ca6351 , 0x14292967 , | |
0x27b70a85 , 0x2e1b2138 , 0x4d2c6dfc , 0x53380d13 , 0x650a7354 , 0x766a0abb , 0x81c2c92e , 0x92722c85 , | |
0xa2bfe8a1 , 0xa81a664b , 0xc24b8b70 , 0xc76c51a3 , 0xd192e819 , 0xd6990624 , 0xf40e3585 , 0x106aa070 , | |
0x19a4c116 , 0x1e376c08 , 0x2748774c , 0x34b0bcb5 , 0x391c0cb3 , 0x4ed8aa4a , 0x5b9cca4f , 0x682e6ff3 , | |
0x748f82ee , 0x78a5636f , 0x84c87814 , 0x8cc70208 , 0x90befffa , 0xa4506ceb , 0xbef9a3f7 , 0xc67178f2 } ; | |
//プロトタイプ宣言(基本関数) | |
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); | |
SHA_INT_TYPE SHA256_rotr(SHA_INT_TYPE,SHA_INT_TYPE); | |
SHA_INT_TYPE SHA256_sigma0(SHA_INT_TYPE); | |
SHA_INT_TYPE SHA256_sigma1(SHA_INT_TYPE); | |
SHA_INT_TYPE SHA256_sum0(SHA_INT_TYPE); | |
SHA_INT_TYPE SHA256_sum1(SHA_INT_TYPE); | |
SHA_INT_TYPE SHA256_ch(SHA_INT_TYPE,SHA_INT_TYPE,SHA_INT_TYPE); | |
SHA_INT_TYPE SHA256_maj(SHA_INT_TYPE,SHA_INT_TYPE,SHA_INT_TYPE); | |
void SHA_Reverse_INT64(const unsigned char *,unsigned __int64); | |
SHA_INT_TYPE SHA_Reverse(SHA_INT_TYPE); | |
//プロトタイプ宣言(SHA) | |
void SHA1_HashBlock(SHA_INT_TYPE *,const unsigned char *); | |
bool SHA1(SHA1_DATA *, const char* , SHA_INT_TYPE); | |
void SHA256_HashBlock(SHA_INT_TYPE *,const unsigned char *); | |
bool SHA256(SHA256_DATA *, const char* , SHA_INT_TYPE); | |
//プロトタイプ(HMAC) | |
bool HMAC_SHA1(SHA1_DATA *,const char*,const char*,SHA_INT_TYPE); | |
void HMAC_SHA1_Copy(const unsigned char*,SHA1_DATA*); | |
bool HMAC_SHA256(SHA256_DATA *,const char*,const char*,SHA_INT_TYPE); | |
void HMAC_SHA256_Copy(const unsigned char*,SHA256_DATA*); | |
//基本関数 | |
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 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); | |
} | |
//右ローテート関数 | |
SHA_INT_TYPE SHA256_rotr(SHA_INT_TYPE r,SHA_INT_TYPE x){ | |
SHA_INT_TYPE rot = r%32; | |
return (x >> rot) | (x << (32-rot)); | |
} | |
SHA_INT_TYPE SHA256_sigma0(SHA_INT_TYPE x){ | |
return SHA256_rotr(7,x) ^ SHA256_rotr(18,x) ^ (x >> 3); | |
} | |
SHA_INT_TYPE SHA256_sigma1(SHA_INT_TYPE x){ | |
return SHA256_rotr(17,x) ^ SHA256_rotr(19,x) ^ (x >> 10); | |
} | |
SHA_INT_TYPE SHA256_sum0(SHA_INT_TYPE x){ | |
return SHA256_rotr(2,x) ^ SHA256_rotr(13,x) ^ SHA256_rotr(22,x); | |
} | |
SHA_INT_TYPE SHA256_sum1(SHA_INT_TYPE x){ | |
return SHA256_rotr(6,x) ^ SHA256_rotr(11,x) ^ SHA256_rotr(25,x); | |
} | |
SHA_INT_TYPE SHA256_ch(SHA_INT_TYPE x,SHA_INT_TYPE y,SHA_INT_TYPE z){ | |
return (x & y)^(~x & z); | |
} | |
SHA_INT_TYPE SHA256_maj(SHA_INT_TYPE x,SHA_INT_TYPE y,SHA_INT_TYPE z){ | |
return (x&y)^(x&z)^(y&z); | |
} | |
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_SHA256_Copy(unsigned char *copy,SHA256_DATA *shd){ | |
SHA_INT_TYPE Value[8]; | |
for(int i=0;i<8;i++)Value[i] = SHA_Reverse(shd->Value[i]); | |
memcpy(copy,Value,32); | |
} | |
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 SHA256_HashBlock(SHA_INT_TYPE *SHA256_H_Data,const unsigned char *data){ | |
SHA_INT_TYPE SIT[64]; | |
SHA_INT_TYPE SIT_d[16] ;//512ビット、64バイト | |
SHA_INT_TYPE a,b,c,d,e,f,g,h; | |
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<=63;t++) SIT[t] = SHA256_sigma1(SIT[t-2]) + SIT[t-7] + SHA256_sigma0(SIT[t-15]) + SIT[t-16]; | |
a = *SHA256_H_Data; | |
b = *(SHA256_H_Data + 1); | |
c = *(SHA256_H_Data + 2); | |
d = *(SHA256_H_Data + 3); | |
e = *(SHA256_H_Data + 4); | |
f = *(SHA256_H_Data + 5); | |
g = *(SHA256_H_Data + 6); | |
h = *(SHA256_H_Data + 7); | |
for(int t=0;t<=63;t++){ | |
SHA_INT_TYPE tmp[2]; | |
tmp[0] = h + SHA256_sum1(e) + SHA256_ch(e,f,g) + SHA256_K_Val[t] +SIT[t]; | |
tmp[1] = SHA256_sum0(a) + SHA256_maj(a,b,c); | |
h = g; | |
g = f; | |
f = e; | |
e = d + tmp[0]; | |
d = c; | |
c = b; | |
b = a; | |
a = tmp[0] + tmp[1]; | |
} | |
*SHA256_H_Data += a; | |
*(SHA256_H_Data + 1) += b; | |
*(SHA256_H_Data + 2) += c; | |
*(SHA256_H_Data + 3) += d; | |
*(SHA256_H_Data + 4) += e; | |
*(SHA256_H_Data + 5) += f; | |
*(SHA256_H_Data + 6) += g; | |
*(SHA256_H_Data + 7) += h; | |
} | |
bool SHA256(SHA256_DATA *sha256d, const char *data , SHA_INT_TYPE size){ | |
SHA_INT_TYPE s,h[8],ns; | |
int cnt=0; | |
unsigned __int64 s64; | |
unsigned char d[64]; | |
if(!sha256d)return false; | |
s = (size)?size:strlen(data); | |
memcpy(h,SHA256_H_Val,sizeof(SHA256_H_Val)); | |
//dataのバイト数が64バイトを超えていたら60バイト未満になるまで処理をする | |
for(SHA_INT_TYPE i=s,j=0;i>=64;i-=64,j+=64)SHA256_HashBlock(h,(const unsigned char*)(data + j)); | |
//パディングに含めるデータのサイズ | |
ns = s%64; | |
//d・・・パディング文字列 | |
memset(d,0,64); | |
//パディングにコピー | |
memcpy(d,data + (s-ns),ns); | |
//d[ns]に0x80を代入 | |
d[ns] = 0x80; | |
//パディングに含めるデータのサイズが56バイト以上だった時の処理 | |
if(ns >= 56){ | |
//パディングに含めるデータのサイズが56バイト以上だったらSHA1_HashBlockを実行する | |
SHA256_HashBlock(h,d); | |
//dの最初~56バイト文NULL文字をセット | |
memset(d,0,56); | |
} | |
//データのサイズをビット数にする | |
s64 = s*8; | |
//データのサイズ(ビット単位)を書き込む | |
SHA_Reverse_INT64(&d[56],s64); | |
//最後の処理 | |
SHA256_HashBlock(h,d); | |
memcpy(sha256d->Value,h,sizeof(h)); | |
sprintf(sha256d->Val_String,"%08X %08X %08X %08X %08X %08X %08X %08X",h[0],h[1],h[2],h[3],h[4],h[5],h[6],h[7]); | |
return true; | |
} | |
bool HMAC_SHA256(SHA256_DATA *sha256d,const char *b_target,const char *b_key,SHA_INT_TYPE tsize){ | |
unsigned char key[65],ipad[64],opad[64]; | |
unsigned char *tk,tk2[32],tk3[96]; | |
SHA_INT_TYPE tks; | |
SHA256_DATA SD,ret; | |
memset(&SD,0,sizeof(SHA256_DATA)); | |
memset(key,0,65); | |
memset(ipad,0x36,64); | |
memset(opad,0x5c,64); | |
if(!sha256d)return false; | |
if(strlen(b_key) > 64){ | |
SHA256(&SD,b_key,0); | |
HMAC_SHA256_Copy(key,&SD); | |
}else{ | |
memcpy(key,(unsigned char*)b_key,strlen(b_key)); | |
} | |
memset(&SD,0,sizeof(SHA256_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)); | |
SHA256(&SD,(char *)tk,tks); | |
HMAC_SHA256_Copy(tk2,&SD); | |
memcpy(tk3,opad,64); | |
memcpy(tk3 + 64 , tk2,32); | |
SHA256(&ret,(char *)tk3,96); | |
memcpy(sha256d,&ret,sizeof(SHA256_DATA)); | |
free(tk); | |
return true; | |
} | |
//メイン関数 | |
int main(void){ | |
char Data[2048],Key[2048]; | |
SHA256_DATA SD256; | |
SHA1_DATA SD1; | |
printf("Data(2048バイト未満) = "); | |
gets(Data); | |
printf("Key(2048バイト未満) = "); | |
gets(Key); | |
SHA1(&SD1,Data,0); | |
SHA256(&SD256,Data,0); | |
printf("\nSHA1 = %s\n",SD1.Val_String); | |
printf("SHA256 = %s\n\n",SD256.Val_String); | |
HMAC_SHA1(&SD1,Data,Key,0); | |
HMAC_SHA256(&SD256,Data,Key,0); | |
printf("HMAC-SHA1 = %s\n",SD1.Val_String); | |
printf("HMAC-SHA256 = %s\n",SD256.Val_String); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment