-
RSA전자서명 실습공부/과거 2013. 11. 26. 00:58반응형
ras_std.c // ras_sv.c // md5.c 따로 소스파일로 만들고, rav_std.c와md5.c는 속성 눌러서 빌드에 참여안함 선택하시고 txt파일이름은 MONEY로해주시면 됩니다요
ras_std.c
#include <stdio.h>
#include <time.h>
#include <io.h>
#include <dos.h>
#include <fcntl.h>
#include <sys\stat.h>
/********************************************************************/
/*********** Function name : CONV_B_to_R (a,B,mn) **********/
/*********** Description : convert bin. into radix **********/
/********************************************************************/
INT64 mask[DHEX]={0x80000000, 0x40000000, 0x20000000, 0x10000000,0x8000000,
0x4000000,0x2000000, 0x1000000, 0x800000,0x400000, 0x200000,
0x100000, 0x080000,0x040000, 0x020000, 0x010000,
0x8000, 0x4000, 0x2000, 0x1000,0x800,
0x400,0x200, 0x100, 0x80,0x40, 0x20,
0x10, 0x08,0x04, 0x02, 0x01
};
void CONV_B_to_R (short *A,INT64 *B,short mn)
{
register int i, j, k;
for(i=mn-1;i>=0;i--) B[i]=0x00;
i = mn*DHEX-1;
for(k=0;k<=mn-1;k++) {
B[k] = 0x00;
for(j=DHEX-1;j>=0;j--) {
B[k] += A[i--] * mask[j];
if(i<0) break
}
if(i<0) break
}
}
/********************************************************************/
/*********** Function name : CONV_R_to_B (A,b,mn) **********/
/*********** Description : convert radix into bin. **********/
/********************************************************************/
void CONV_R_to_B (INT64 *A,short *B,short mn)
{
register int i, j, k;
for(i=0;i<mn*DHEX;i++) B[i]=0;
k = mn*DHEX-1;
for(i=0;i<=mn-1;i++) {
for(j=0;j<=DHEX-1;j++) {
B[k--] = (A[i]>>j)&0x01;
if(k<0) break
}
if(k<0) break
}
}
/********************************************************************/
/*********** Function name : rand_g (a,n) **********/
/*********** Description : n-bits random **********/
/*********** number generator. **********/
/********************************************************************/
void rand_g(short *out,short n)
{
register int j,k;
short x;
//long t;
srand((unsigned)(time(NULL)));
//delay(100);
j=0;
while(1) {
x = rand();
for(k=0;k<15;k++) {
out[n-1-j] = (x>>k) & 0x01;
j++;
if(j>=n) return
}
}
}
/********************************************************************/
/***** Function name : Modular(C, N mn) *****/
/***** Description : C = C mod N *****/
/********************************************************************/
void Modular (INT64 *X, INT64 *N, short mn)
{
register int i, j, k;
short shift,posit;
INT64 arryA[2*mb+1]={0,},arryN[2*mb+1]={0,};
INT64 acumA, acumB, acumN, acumQ;
INT32 acumC;
acumN = N[mn-1] + 0x01;
while(1) {
for(k=2*mn-1;k>=0;k--)
if(X[k]>0x00)
break
if(k<=mn-1)
break
acumA = X[k]*rdx+X[k-1];
acumQ = acumA / acumN;
if(acumQ>(rdx-1))
acumQ = rdx-1;
shift = k - mn; /** shift number **/
acumC = 0x00;
for(k=0;k<=mn-1;k++) {
acumA = N[k]*acumQ + acumC;
acumC = acumA >>DHEX;
acumA = acumA & LAND;
j=k+shift;
if(X[j]<acumA) {
X[j] += rdx;
posit=j;
while((X[j+1])==0 && (j<(mn+shift))){
X[j+1] += rdx-1;
j++;
}X
[j+1] -= 0x01;
j=posit;
}X
[j] = (X[j]-acumA) & LAND;
}X
[mn+shift] = X[mn+shift]-acumC;
}
while(1) {
for(i=mn-1;i>=0;i--) {
if((X[i]&LAND) != (N[i]&LAND)) {
if((X[i]&LAND)>(N[i]&LAND))
break
else
return(0);
}
}
acumA = X[mn-1];
acumA = acumA / acumN;
if(acumA==0x00) {
for(i=0;i<=mn-1;i++) {
if(X[i]<N[i]) {
X[i] += rdx;
posit = i;
while( (X[i+1]==0) && (i<mn)) {
X[i+1] += rdx-1;
i++;
}X
[i+1] -= 0x01;
i = posit;
}X
[i] = (X[i]-N[i])&LAND;
}
}
else {
acumC = 0x00;
for(i=0;i<=mn-1;i++) {
acumB = N[i]*acumA + acumC;
acumC = acumB>>DHEX;
acumB = acumB & LAND;
if(X[i]<acumB) {
X[i] += rdx;
posit = i;
while( (X[i+1]==0) && (i<mn)) {
X[i+1] += rdx-1;
i++;
}X
[i+1] -= 0x01;
i = posit;
}X
[i] = (X[i]-acumB)&LAND;
}
}
}
}
/********************************************************************/
/***** Function name : Conv_mma(A,B,C,N,mn) (Conventional) *****/
/***** Description : C= A*B mod N *****/
/********************************************************************/
void Conv_mma (INT64 *A,INT64 *B,INT64 *C,INT64 *N, short mn)
{
register int i, j, k;
INT64 arryC[mb*2],X[mb*2]; /** temporary arrys **/
INT64 acumA; /** temporary acumulators **/
INT32 acumC;
for(k=2*mn-1;k>=0;k--) arryC[k] = 0x00;
for(i=0;i<=mn-1;i++) {
if(A[i]>0x00) {
acumC = 0x00;
for(j=0;j<=mn-1;j++) {
acumA = A[i]*B[j] + arryC[i+j] + acumC;
arryC[i+j] = acumA &LAND;
acumC = acumA >>DHEX;
}
arryC[i+j] = acumC;
}
}
for(i=2*mn-1;i>=0;i--)
X[i]=arryC[i];
Modular (X, N, mn);
for(i=0;i<=mn-1;i++)
C[i] = X[i];
}
/********************************************************************/
/*********** Function name : CONV_B_to_O (a,B,mn) **********/
/*********** Description : convert bin. into octet **********/
/********************************************************************/
INT64 o_mask[8] = { 0x80,0x40, 0x20, 0x10, 0x08,0x04, 0x02, 0x01};
void CONV_B_to_O (short *A,INT64 *B, short mn)
{
register int i, j, k;
i = mn*OCT-1;
for(k=0;k<=mn-1;k++) {
B[k]=0x00;
for(j=7;j>=0;j--) {
B[k] += A[i--] * o_mask[j];
if(i<0) break
}if(i<0) break
}
}
/********************************************************************/
/*********** Function name : CONV_O_to_B (A,b,mn) **********/
/*********** Description : convert octet into bin. **********/
/********************************************************************/
void CONV_O_to_B (INT64 *A,short *B,short mn)
{
register int i, j, k;
for(i=0;i<mn*OCT;i++) B[i]=0;
k = mn*OCT-1;
for(i=0;i<=mn-1;i++) {
for(j=0;j<=7;j++) {
B[k--] = (A[i]>>j)&0x01;
if(k<0) break
}if(k<0) break
}
}
/********************************************************************/
/***** Function name : WM_Left_Pow(A,E,C,N,mn) *****/
/***** Description : C= A^E mod N *****/
/********************************************************************/
void LeftTORight_Pow(INT64 *A, INT64 *E, INT64 *C, INT64 *N, short mn)
{
register int i;
INT64 arryC[mb]={0,};
short e[m]={0,};
for(i=0;i<mn;i++)
C[i] = 0x00;
CONV_R_to_B(E, e, mn);
arryC[0] = 0x01;
for(i=0;i<mn*DHEX;i++)
{
Conv_mma(arryC, arryC, arryC, N, mn);
if(e[i] == 1)
Conv_mma(arryC, A, arryC, N, mn);
}
for(i=0;i<mn;i++)
C[i] = arryC[i];
}
ras_sv.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* 상수정의/
#define m 1024 // 모듈러의비트수
define mp 512 // 비밀소수의비트수
define mq 512 // 비밀소수의비트수
define HASH 128
#define LEN_PS 91 // 패딩스트링의크기
define DATA_LEN 53
#define HASH_LEN 34
#define DHEX 32
#define OCT 8
#define Char_NUM 8
#define B_S 64
#define mb m/DHEX
#define hmb mb/2
#define mpb mp/DHEX
#define mqb mq/DHEX
#define rdx 0x100000000
/* 타입정의/
typedef unsigned long int ULINT;
typedef unsigned _int64 INT64;
typedef unsigned _int32 INT32;
/* 함수선언/
void RSA_Signature(); // RSA 서명함수
oid RSA_Verification(); // RSA 서명검증함수
nt get_from_file(FILE* fptr, short *a, short mn); // 파일로부터데이터를읽어이진형태로저장하는함수
oid put_to_file(FILE* fptr, short *a, short mn); // 이진데이터를바이트형태로변환하여파일에저장하는함수
oid put_to_message(unsigned char* msg, short *a, short mn); // 이진데이터를바이트형태로변환하여메시지버퍼에저장하는함수
oid CONV_O_to_B (INT64 *A, short *B, short mn); // octet를inary로변환하는함수
oid CONV_B_to_O (short *A, INT64 *B, short mn); // binary를ctet으로변환하는함수
oid CONV_R_to_B (INT64 *A, short *B, short mn); // Radix를inary로변환하는함수
oid CONV_B_to_R (short *A, INT64 *B, short mn); // binary를adix로변환하는함수
oid rand_g(short *out,short n); // 랜덤수를생성하여이진형태로저장하는함수
oid Modular (INT64 *X, INT64 *N, short mn); // 모듈러연산을수행하는함수
oid Conv_mma (INT64 *A,INT64 *B,INT64 *C,INT64 *N, short mn); //고전적인모듈러감소연산을수행하는함수
oid LeftTORight_Pow(INT64 *A, INT64 *E, INT64 *C, INT64 *N, short mn); // Left toRight 멱승을수행하는함수
* 전역변수/
INT32 LAND=0xFFFFFFFF;
// 공개키파라미터
NT64 N[mb]; // 모듈러 (= p * q)
INT64 E[mb]; // 공개키
INT64 D[mb]; // 비밀키
// 서명과검증에사용되는버퍼이진binary) 형태
short s[m]; // 서명값
hort h[HASH_LEN*8]; // 해쉬값서명
short v_h[m]; // 해쉬값검증
short ps[LEN_PS*8]; // 패딩스트링
/ 서명과검증에사용되는버퍼Radix와ctet 형태
INT64 S[mb]; // 서명값서명
INT64 V_S[mb]; // 서명값검증
INT64 H[mb]; // 해쉬값Radix)
INT64 HDATA[HASH_LEN]; // 해쉬값octet - 서명
INT64 SB[mb*4]; // 서명블록8 bit - 서명
INT64 SB1[mb]; // 서명블록16 bit)
INT64 V_SB[mb*4]; // 서명블록8 bit - 검증
INT64 V_HDATA[HASH_LEN]; // 해쉬값octet - 검증
INT64 O_PS[LEN_PS*8]; // 패딩스트링octet)
// MD5를나타내는식별값
nsigned char md5_num[18] = {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86,
0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00,
0x04, 0x10};
#include "rsa_std.c"
#include "md5.c"
void main(int argc, char* argv[])
{
int select;
// 서명과서명검증선택
rintf("* 1. RSA 서명. RSA 서명검증'5cn");
printf("- 선택하시오 ");
scanf("%d", &select);
// 선택한항목실행
f(select == 1)
RSA_Signature();
else if(select == 2)
RSA_Verification();
else
printf("* 잘못입력하셨습니다\n");
system("PAUSE");
}
void RSA_Signature(){
int i, j, cnt;
BYTE hash_text[HASH_LEN] = {0, };
char file_name[32] = {0, }, s_file_name[32] = {0, };
FILE *fptr;
// 서명에사용할비밀키파일을연다
f((fptr = fopen("secret_key.txt", "rb")) == NULL) {
printf("file open failed!!\n");
exit(1);
}// 파일로부터비밀키와모듈라을저장한다
for(i=mb-1; i>=0; i--) fscanf(fptr, "%I64x ", &N[i]);
for(i=mb-1; i>=0; i--) fscanf(fptr, "%I64x ", &D[i]);
fclose(fptr);
// 서명할파일명입력
rintf("* 서명할파일명을입력하시오 ");
scanf("%s", file_name);
// 파일열기
f((fptr = fopen(file_name, "rb")) == NULL) {
printf("File opne failed!\n");
exit(1);
}
MD5(fptr, hash_text); // MD5 해쉬
close(fptr);
// MD5 식별값을해쉬값에이어서추가한다
or(i=0; i<18; i++)
hash_text[i+16] = md5_num[18-i-1];
// 해쉬데이터를이진값으로변환한다
nt = HASH_LEN*8-1;
for(i=0; i<HASH_LEN; i++) {
for(j=0; j<8; j++) {
h[cnt] = (hash_text[i] >> j) & 0x01;
cnt--;
}
}
CONV_B_to_O(h, HDATA, HASH_LEN); // 이진데이터를ctet으로변환
* EMSA-PKCS #1-v1.5 패딩/
// [00|01|PS|00|T] (T = 해쉬알고리즘식별값 해쉬값
for(i=0; i<mb*4; i++)
SB[i] = 0xFF;
SB[mb*4-1] = 0x00;
SB[mb*4-2] = 0x01;
SB[HASH_LEN] = 0x00;
for(i=HASH_LEN-1; i>=0; i--)
SB[i] = HDATA[i];
for(i=mb*4-1; i>=0; i=i-4)
SB1[i/4] = (SB[i] << (DHEX-OCT)) + (SB[i-1] << (OCT+OCT)) + (SB[i-2] << OCT) +
SB[i-3];
/* 패딩과정종료/
/*** c = h(m) ^ d mod n (m-bit) ***/
LeftTORight_Pow(SB1, D, S, N, mb); // 최종메시지에서명을한다
ONV_R_to_B(S, s, mb); // Radix를이진데이터로변환
/ 서명을저장할파일이름설정예 MONEY.txt -> MONEY.sgn)
for(i=0;;i++) {
if(file_name[i] == '.') {
s_file_name[i] = '\0'
strcat(s_file_name, ".sgn");
break
}
s_file_name[i] = file_name[i];
}// 서명데이터를저장할파일열기
f((fptr = fopen(s_file_name, "wb")) == NULL) {
printf("File open failed!\n");
exit(1);
}
put_to_file(fptr, s, m/Char_NUM); // 서명데이터를파일로저장
rintf("\n* The Signature is completed.\n\n");
fclose(fptr);
}
void RSA_Verification()
{
int i;
BYTE v_text[HASH_LEN] = {0, };
BYTE hash_text[16] = {0, };
char file_name[32] = {0, }, s_file_name[32] = {0, };
FILE *fptr;
// 서명자의공개키파일열기
f((fptr = fopen("public_key.txt", "rb")) == NULL) {
printf("file open failed!!\n");
exit(1);
}// 파일로부터공개키와모듈라을저장한다
or(i=mb-1; i>=0; i--) fscanf(fptr, "%I64x ", &N[i]);
for(i=mb-1; i>=0; i--) fscanf(fptr, "%I64x ", &E[i]);
fclose(fptr);
// 검증할파일명입력
rintf("* 검증할파일명을입력하시오 ");
scanf("%s", file_name);
// 파일열기
f((fptr = fopen(file_name, "rb")) == NULL) {
printf("File open failed!\n");
exit(1);
}
MD5(fptr, hash_text); // MD5 해쉬
close(fptr);
// 서명파일명입력
rintf("* 서명파일명을입력하시오.sgn) : ");
scanf("%s", file_name);
// 서명파일열기
f((fptr = fopen(file_name, "rb")) == NULL) {
printf("File open failed!\n");
exit(1);
}
get_from_file(fptr, s, m/Char_NUM); // 파일로부터서명데이터를읽어온다
ONV_B_to_R(s, V_S, mb); // 이진데이터를adix로변환
eftTORight_Pow(V_S, E, H, N, mb); // 서명검증
/ 데이터변환Radix -> Binary -> Octet)
CONV_R_to_B(H, v_h, mb);
CONV_B_to_O(v_h, V_SB, mb*4);
// 패딩부분을제외하고해쉬데이터만추출한다
or(i=HASH_LEN-1; i>=0; i--)
V_HDATA[i] = V_SB[i];
// MD5 식별값을제외하고해쉬값만비교하여
/ 검증의성공여부를확인한다
or(i=0; i<16; i++) {
if(V_HDATA[i] != hash_text[i]) {
printf("The Verification is failed!\n");
return
}
}printf("\n* The Verification is completed!\n");
fclose(fptr);
}
// 파일로부터데이터를읽어와이진형태로저장
nt get_from_file(FILE* fptr, short *a, short mn)
{
int i,j;
short flag=1, cnt=0,mm;
unsigned char b[m/Char_NUM]={0,};
mm = mn*Char_NUM;
for(i=0; i< mm ;i++)
a[i]=0;
// 파일에서한바이트씩읽는다
or(i=0; i< mn ;i++)
{
if(fscanf(fptr,"%c",&b[i])==EOF)
{
if(i==0)
{
flag=-1;
return(flag);
}
flag=0;
for( ; i<mn ;i++)
b[i] = '\0'
break
}
}
cnt=0;
// 바이트단위의데이터를이진형태로변환
or (i=mn-1;i>=0;i--)
{
for(j=0;j<Char_NUM;j++)
{
a[cnt++] = (b[i]>>j) & 0x01;
}
}
return(flag);
}
// 이진형태의데이터를바이트단위로변환하여파일로저장
oid put_to_file(FILE* fptr, short *a, short mn)
{
int i,j;
short cnt=0, mm;
unsigned char b[m/Char_NUM]={0,};
unsigned char mask[Char_NUM] = {0x01,0x02,0x04,0x08,
0x10,0x20,0x40,0x80};
mm=mn*Char_NUM;
cnt=0;
// 이진형태의데이터를바이트형태로변환한다
or(i=mn-1;i>=0;i--) {
b[i]=0x00;
for(j=0;j<Char_NUM;j++) {
b[i] = b[i] + a[cnt++] * mask[j];
}
}
// 변환한데이터를메시지버퍼에저장한다
or(i=0;i<mn;i++)
fprintf(fptr, "%c", b[i]);
}
// 이진형태의데이터를바이트단위로변환하여저장
oid put_to_message(unsigned char* msg, short *a, short mn)
{
register i,j;
short cnt=0, mm;
unsigned char b[m/Char_NUM]={0,};
unsigned char mask[Char_NUM] = {0x01,0x02,0x04,0x08,
0x10,0x20,0x40,0x80};
mm=mn*Char_NUM;
cnt=0;
// 이진형태의데이터를바이트형태로변환한다
or(i=mn-1;i>=0;i--) {
b[i]=0x00;
for(j=0;j<Char_NUM;j++) {
b[i] = b[i] + a[cnt++] * mask[j];
}
}// 변환한데이터를메시지버퍼에저장한다
or (i=mn-1;i>=0;i--)
msg[i] = b[i];
}
md5.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* 상수정의/
#define HASH_BLOCK 64 // 해쉬블록크기byte)
#define HASH_DATA 16 // 해쉬값의크기byte)
// 순환이동횟수
define S11 7
#define S12 12
#define S13 17
#define S14 22
#define S21 5
#define S22 9
#define S23 14
#define S24 20
#define S31 4
#define S32 11
#define S33 16
#define S34 23
#define S41 6
#define S42 10
#define S43 15
#define S44 21
/* 매크로함수/
#define BTOW(a,b,c,d) ( ((a << 24) + (b << 16) + (c << 8) + d) ) // byte를ord로변환
define CIR_SHIFT(X,n) ( ((X) << n) | ((X) >> (32-n)) ) // 32비트왼쪽순환이동
/ 부울함수
define F(X,y,z) ( ((X)&(y)) | ((~X)&(z)) )
#define G(X,y,z) ( ((X) & (z)) | ((y) & (~(z))) )
#define H(X,y,z) ( ((X) ^ (y) ^ (z)) )
#define I(X,y,z) ( (y) ^ ((X) | (~(z))) )
/* 타입정의/
typedef unsigned char BYTE;
typedef unsigned int UINT;
typedef unsigned __int64 UINT64;
/* 함수선언/
void padding(BYTE* in, UINT64 msg_len); //MD5 패딩함수
oid MD5_init();
// MD5 초기화함수
oid MD5(FILE* fptr, BYTE* result);
// MD5 해쉬함수
oid MD5_digest(BYTE *in);
// MD5 메시지igest 함수
oid FF(UINT *a, UINT b, UINT c, UINT d, UINT M, int s, UINT T); // F 함수
oid GG(UINT *a, UINT b, UINT c, UINT d, UINT M, int s, UINT T); // G 함수
oid HH(UINT *a, UINT b, UINT c, UINT d, UINT M, int s, UINT T); // H 함수
oid II(UINT *a, UINT b, UINT c, UINT d, UINT M, int s, UINT T); // I 함수
oid make_Bit128(BYTE in[16], UINT a, UINT b, UINT c, UINT d); // word 단위의해쉬값을yte 단위로변환하는함수
* 전역변수/
static UINT init_reg[4]; // 초기레지스터
tatic BYTE digest[HASH_DATA]; // 해쉬값
tatic int isAddpad = 0;
static UINT T[64] = {0xD76AA478, 0xE8C7B756, 0x242070DB, 0xC1BDCEEE, 0xF57C0FAF,
0x4787C62A, 0xA8304613, 0xFD469501,
0x698098D8, 0x8B44F7AF, 0xFFFF5BB1, 0x895CD7BE,
0x6B901122, 0xFD987193, 0xA679438E, 0x49B40821,
0xF61E2562, 0xC040B340, 0x265E5A51, 0xE9B6C7AA,
0xD62F105D, 0x02441453, 0xD8A1E681, 0xE7D3FBC8,
0x21E1CDE6, 0xC33707D6, 0xF4D50D87, 0x455A14ED,
0xA9E3E905, 0xFCEFA3F8, 0x676F02D9, 0x8D2A4C8A,
0xFFFA3942, 0x8771F681, 0x6d9D6122, 0xFDE5380C,
0xA4BEEA44, 0x4BDECFA9, 0xF6BB4B60, 0xBEBFBC70,
0x289B7EC6, 0xEAA127FA, 0xD4EF3085, 0x04881D05,
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391};
/////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////
/*
void main()
{
int i;
char file_name[32] = {0,};
BYTE result[HASH_DATA] = {0,};
FILE* fp;
// 파일이름입력
rintf("* 파일이름을입력하세요 ");
scanf("%s", file_name);
// 파일열기
f((fp = fopen(file_name, "rb")) == NULL)
{
printf("* File open failed!\n");
exit(1);
}
MD5(fp, result); // MD5 해쉬
/ 해쉬결과출력
or(i=0;i<HASH_DATA;i++)
printf("%3X", result[i]);
printf("\n");
fclose(fp);
}*/
// 패딩함수
oid padding(BYTE* in, UINT64 msg_len)
{
int i;
BYTE* ptr = (BYTE*)&msg_len;
// 메시지가48비트보다작은경우와48비트보다큰경우로나누어처리
/ 448비트보다큰경우에는12비트의블록을추가하여패딩을수행한다
f((msg_len % HASH_BLOCK) < 56)
{
in[msg_len % HASH_BLOCK] = 0x80; // 메시지다음비트에 추가
sg_len *= 8; // 메시지길이계산
or(i=0;i<8;i++)
in[HASH_BLOCK-i-1] = *(ptr+(7-i)); // 블럭끝의4bit에메시지길이를저장
'7delse
{
in[msg_len % HASH_BLOCK] = 0x80; // 메시지다음비트에 추가
sg_len *= 8; // 메시지길이계산
sAddpad = 1;
for(i=0;i<8;i++)
in[HASH_BLOCK*2-i-1] = *(ptr+(7-i)); // 블럭끝의4bit에메시지길이를저장
'7d
}
// 초기값설정
oid MD5_init()
{
init_reg[0] = 0x67452301;
init_reg[1] = 0xefcdab89;
init_reg[2] = 0x98badcfe;
init_reg[3] = 0x10325476;
}
// MD5 해쉬함수
oid MD5(FILE* fptr, BYTE* result)
{
int i, size = 0;
BYTE msg[HASH_BLOCK*2] = {0,};
UINT64 f_size = 0;
MD5_init(); // 초기화
hile((size = fread(msg, sizeof(BYTE), HASH_BLOCK, fptr)))
{
f_size += size; // 파일크기
f(size < HASH_BLOCK)
padding(msg, f_size); // 마지막블록에서패딩수행
D5_digest(msg); // 메시지igest 수행
f(isAddpad) MD5_digest(msg + HASH_BLOCK);
memset(msg, 0, HASH_BLOCK*2);
}
for(i=0;i<HASH_DATA;i++)
result[i] = digest[i];
}
// MD5 메시지igest 함수
oid MD5_digest(BYTE *in)
{
int i;
UINT a, b, c, d;
UINT X[16] = {0,};
// 512비트메시지블록을2비트6개의워드로변환한다
or(i=0;i<HASH_BLOCK;)
{
X[i/4] = BTOW(in[i+3], in[i+2], in[i+1], in[i]);
i += 4;
}
a = init_reg[0]; b = init_reg[1]; c = init_reg[2]; d = init_reg[3]; // 초기값설정
/ MD5 라운드
/ FF/GG/HH/II (레지스터, 레지스터, 레지스터, 레지스터, 워드, 순환이동횟수 라운드상수
/* Round 1 */
FF (&a, b, c, d, X[ 0], S11, T[0]); /* 1 */
FF (&d, a, b, c, X[ 1], S12, T[1]); /* 2 */
FF (&c, d, a, b, X[ 2], S13, T[2]); /* 3 */
FF (&b, c, d, a, X[ 3], S14, T[3]); /* 4 */
FF (&a, b, c, d, X[ 4], S11, T[4]); /* 5 */
FF (&d, a, b, c, X[ 5], S12, T[5]); /* 6 */
FF (&c, d, a, b, X[ 6], S13, T[6]); /* 7 */
FF (&b, c, d, a, X[ 7], S14, T[7]); /* 8 */
FF (&a, b, c, d, X[ 8], S11, T[8]); /* 9 */
FF (&d, a, b, c, X[ 9], S12, T[9]); /* 10 */
FF (&c, d, a, b, X[10], S13, T[10]); /* 11 */
FF (&b, c, d, a, X[11], S14, T[11]); /* 12 */
FF (&a, b, c, d, X[12], S11, T[12]); /* 13 */
FF (&d, a, b, c, X[13], S12, T[13]); /* 14 */
FF (&c, d, a, b, X[14], S13, T[14]); /* 15 */
FF (&b, c, d, a, X[15], S14, T[15]); /* 16 */
/* Round 2 */
GG (&a, b, c, d, X[ 1], S21, T[16]); /* 17 */
GG (&d, a, b, c, X[ 6], S22, T[17]); /* 18 */
GG (&c, d, a, b, X[11], S23, T[18]); /* 19 */
GG (&b, c, d, a, X[ 0], S24, T[19]); /* 20 */
GG (&a, b, c, d, X[ 5], S21, T[20]); /* 21 */
GG (&d, a, b, c, X[10], S22, T[21]); /* 22 */
GG (&c, d, a, b, X[15], S23, T[22]); /* 23 */
GG (&b, c, d, a, X[ 4], S24, T[23]); /* 24 */
GG (&a, b, c, d, X[ 9], S21, T[24]); /* 25 */
GG (&d, a, b, c, X[14], S22, T[25]); /* 26 */
GG (&c, d, a, b, X[ 3], S23, T[26]); /* 27 */
GG (&b, c, d, a, X[ 8], S24, T[27]); /* 28 */
GG (&a, b, c, d, X[13], S21, T[28]); /* 29 */
GG (&d, a, b, c, X[ 2], S22, T[29]); /* 30 */
GG (&c, d, a, b, X[ 7], S23, T[30]); /* 31 */
GG (&b, c, d, a, X[12], S24, T[31]); /* 32 */
/* Round 3 */
HH (&a, b, c, d, X[ 5], S31, T[32]); /* 33 */
HH (&d, a, b, c, X[ 8], S32, T[33]); /* 34 */
HH (&c, d, a, b, X[11], S33, T[34]); /* 35 */
HH (&b, c, d, a, X[14], S34, T[35]); /* 36 */
HH (&a, b, c, d, X[ 1], S31, T[36]); /* 37 */
HH (&d, a, b, c, X[ 4], S32, T[37]); /* 38 */
HH (&c, d, a, b, X[ 7], S33, T[38]); /* 39 */
HH (&b, c, d, a, X[10], S34, T[39]); /* 40 */
HH (&a, b, c, d, X[13], S31, T[40]); /* 41 */
HH (&d, a, b, c, X[ 0], S32, T[41]); /* 42 */
HH (&c, d, a, b, X[ 3], S33, T[42]); /* 43 */
HH (&b, c, d, a, X[ 6], S34, T[43]); /* 44 */
HH (&a, b, c, d, X[ 9], S31, T[44]); /* 45 */
HH (&d, a, b, c, X[12], S32, T[45]); /* 46 */
HH (&c, d, a, b, X[15], S33, T[46]); /* 47 */
HH (&b, c, d, a, X[ 2], S34, T[47]); /* 48 */
/* Round 4 */
II (&a, b, c, d, X[ 0], S41, T[48]); /* 49 */
II (&d, a, b, c, X[ 7], S42, T[49]); /* 50 */
II (&c, d, a, b, X[14], S43, T[50]); /* 51 */
II (&b, c, d, a, X[ 5], S44, T[51]); /* 52 */
II (&a, b, c, d, X[12], S41, T[52]); /* 53 */
II (&d, a, b, c, X[ 3], S42, T[53]); /* 54 */
II (&c, d, a, b, X[10], S43, T[54]); /* 55 */
II (&b, c, d, a, X[ 1], S44, T[55]); /* 56 */
II (&a, b, c, d, X[ 8], S41, T[56]); /* 57 */
II (&d, a, b, c, X[15], S42, T[57]); /* 58 */
II (&c, d, a, b, X[ 6], S43, T[58]); /* 59 */
II (&b, c, d, a, X[13], S44, T[59]); /* 60 */
II (&a, b, c, d, X[ 4], S41, T[60]); /* 61 */
II (&d, a, b, c, X[11], S42, T[61]); /* 62 */
II (&c, d, a, b, X[ 2], S43, T[62]); /* 63 */
II (&b, c, d, a, X[ 9], S44, T[63]); /* 64 */
// 이전초기값과결과값을더하여다음블록의해쉬과정에서초기값으로사용된다
nit_reg[0] += a;
init_reg[1] += b;
init_reg[2] += c;
init_reg[3] += d;
// word 단위의결과값을yte로변환한다
ake_Bit128(digest, init_reg[0], init_reg[1], init_reg[2], init_reg[3]);
}
void FF(UINT *a, UINT b, UINT c, UINT d, UINT M, int s, UINT T)
{
*a = b + CIR_SHIFT((*a + F(b,c,d) + M + T), s);
}
void GG(UINT *a, UINT b, UINT c, UINT d, UINT M, int s, UINT T)
{
*a = b + CIR_SHIFT((*a + G(b,c,d) + M + T), s);
}
void HH(UINT *a, UINT b, UINT c, UINT d, UINT M, int s, UINT T)
{
*a = b + CIR_SHIFT((*a + H(b,c,d) + M + T), s);
}
void II(UINT *a, UINT b, UINT c, UINT d, UINT M, int s, UINT T)
{
*a = b + CIR_SHIFT((*a + I(b,c,d) + M + T), s);
}
void make_Bit128(BYTE in[16], UINT a, UINT b, UINT c, UINT d)
{
int i;
for(i=0;i<16;i++)
{
if(i < 4)
in[i] = ((a & ((UINT)0x000000FF << (i*8))) >> (i*8));
else if(i < 8)
in[i] = ((b & ((UINT)0x000000FF << ((i%4)*8))) >> ((i%4)*8));
else if(i < 12)
in[i] = ((c & ((UINT)0x000000Ff << ((i%4)*8))) >> ((i%4)*8));
else
in[i] = ((d & ((UINT)0x000000FF << ((i%4)*8))) >> ((i%4)*8));
}
}
'공부 > 과거' 카테고리의 다른 글
AES의 쉬프트로우,서브바이트 C로구현 (0) 2013.10.21 C언어 계산기라고말하기도 창피한 사칙연산기 (0) 2013.10.03 MFC로 좌표때려박기로 구현 (0) 2013.10.01