본문 바로가기
알고리즘 구상

[알고리즘] CRC16 테이블을 이용한 데이터 암호화

by 코딩히어로 2022. 9. 19.
728x90

1


임베디드 프로젝트를 진행 중 RF LF 통신의 ID값을 암호화해달라는 요청이 있었습니다

일반적으로 많은 암호화 라이브러리가 존재하지만 해당 프로젝트에서 사용된 칩의 사양 자체가

워낙 낮다 보니 새로운 방식의 알고리즘을 통한 방법이 필요했습니다

 

그래서 기본적으로 사용해 오던 CRC16 테이블 방식에서 알고리즘을 추가하여

전체 ID를 암호화하는 방식을 구상했습니다

 

기본적으로 암호화가 진행될 아이디는 난수+아이디로 구성됩니다

여기에 사용될 난수는 아이디를 전달하는 입장에서 발생시키고

받는 쪽에서는 해당 난수를 통해 CRC16의 역변환을 실행합니다

 

static unsigned char auchCRCHi[] = {
   0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
   0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
   0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
   0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
   0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81,
   0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
   0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
   0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
   0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
   0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
   0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
   0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
   0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
   0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
   0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
   0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
   0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
   0x40
};
static unsigned char auchCRCLo[] = {
   0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4,
   0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
   0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD,
   0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
   0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7,
   0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
   0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE,
   0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
   0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2,
   0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
   0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB,
   0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
   0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91,
   0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
   0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88,
   0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
   0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80,
   0x40
};

암호화에 사용될 2개의 테이블을 구성합니다 배열의 값은 사용자마다 어떻게 구성하든 상관없습니다

void data_to_pass(unsigned char* arr,int len){
	unsigned char uchCRCHi = *arr++;
	unsigned char compress,result;
	len-=1;
	printf("%02x,",uchCRCHi);
	while(len--){
		compress = auchCRCHi[uchCRCHi]^*arr++;
		result = auchCRCLo[uchCRCHi]^compress;
		printf("%02x,",result);
	}

	printf("\n");
}
void pass_to_data(unsigned char* arr,int len){
	unsigned char uchCRCHi = *arr++;
	unsigned char compress,result;
	printf("%02x,",uchCRCHi);
	len-=1;
	while(len--){
		compress = *arr++^auchCRCLo[uchCRCHi];
		result = compress^auchCRCHi[uchCRCHi];
		printf("%02x,",result);
	}
	
}

핵심이 될 암호화 함수와 해독 함수를 구현합니다

암호화 함수를 간단하게 설명하면 첫 번째 테이블에서 난수를 통해 인자에 접근합니다

이렇게 가져온 첫번째 테이블의 인자 값과 암호화할 아이디 한자리를 xor 합니다

그 결괏값을 두 번째 테이블에서 가져온 인자 값과 다시 xor해준 값을 결과로 출력합니다

 

위 순서대로 아이디 전체 자릿수를 암호화하면 난수를 제외한 모든 자리의 숫자가 변경됩니다

받는 쪽에서는 암호화의 역순으로 해독을 진행합니다

int main(int argc, char* argv[]) {
	unsigned char arr[] = {0x02,0x03,0x00,0x64,0xa0,0x04,0xc3,0xa8,0x40,0xaa,0xee};
	data_to_pass(arr,11);
	
	unsigned char arr1[] = {0x02,0x43,0x40,0x24,0xe0,0x44,0x83,0xe8,0x00,0xea,0xae};
	pass_to_data(arr1,11);
	
	return 0;
}

예를 들어 위의 arr []의 값을 암호화하면 arr1 []의 값이 출력됩니다

원데이터와는 다른 숫자의 값들로 채워져 있는데 난수인 0x02를 가지고

arr1 []을 해독하면 arr []의 값을 읽을 수 있습니다

 

해당 암호화의 장점은 테이블의 값을 모르는 사람은 해독을 할 수 없다는 것입니다

물론 계산식을 통해 유추가 가능하겠지만 두 개의 테이블 값의 경우의 수는 약 65,000개가 되기

때문에 테이블을 어떻게 구성하느냐에 따라 암호화 데이터가 다르게 출력됩니다

728x90
반응형

댓글