티스토리 뷰
6번 문항은 암호구현 문제입니다. 비트슬라이싱이라는 기법을 사용하지 않으면 0점을 주는 무시무시한 문제입니다. 하지만 이번 문항을 계기로 비트슬라이싱에 대해 알게 되어 좋았습니다.
처음 문제를 풀 때 코드가 잘못된 걸 보고 0초만에 최적화를 시켰었습니다 (사실 문제가 잘못된 거여서 말해줘서 수정해주심) 같은 팀원인 친구가 2번도 문제 잘못됐다고 지적해서 바꿨었는데 이런 부분에서 가산점은 없어서 아쉽습니다... (익명으로 질문해서 우리 팀인지 당연히 모르신다....)
최적화를 시킬 코드는 해당 홈페이지에 게시되어 있고, 아두이노 우노 버전을 활용하여 문제를 해결하여야 합니다.
비트슬라이싱을 활용하여 최적화를 진행해 보겠습니다.
1. 비트 슬라이싱
비트 슬라이싱이란 작은 비트 모듈을 모아 큰 비트 프로세서를 제작하는 기술입니다. 다음과 같은 예에서 4번의 XOR 연산을 4bit 프로세서라는 가정으로 1번의 XOR 연산으로 처리할 수 있습니다.
2. 카르노 맵
비트 슬라이싱을 적용하기 위해 카르노 맵을 이용하였습니다. 카르노 맵을 이용하여 특정 연산 f에 대해 비트 단위로 표와 식을 만들 수 있습니다.
https://ko.wikipedia.org/wiki/%EC%B9%B4%EB%85%B8_%EB%A7%B5
3. 비트슬라이싱과 S-box
주어진 S-box 연산에 카르노맵과 비트슬라이싱을 적용한 결과는 다음과 같습니다.
이를 s-box에 적용하면 다음과 같이 f,g,h,k 함수를 활용하여 s-box 값을 구할 수 있습니다.
u32 new_s_box_gen(u32 text){
u32 output = 0;
// transpose
u8 num1 = (u8)(((text & 0x80000000) >> 24) | ((text & 0x8000000) >> 21) | ((text & 0x800000)
>> 18) | ((text & 0x80000) >> 15) | ((text & 0x8000) >> 12) | ((text & 0x800) >> 9) | ((text & 0x80) >>
6) | ((text & 0x8) >> 3));
u8 num2 = (u8)(((text & 0x40000000) >> 23) | ((text & 0x4000000) >> 20) | ((text & 0x400000)
>> 17) | ((text & 0x40000) >> 14) | ((text & 0x4000) >> 11) | ((text & 0x400) >> 8) | ((text & 0x40) >>
5) | ((text & 0x4) >> 2));
u8 num3 = (u8)(((text & 0x20000000) >> 22) | ((text & 0x2000000) >> 19) | ((text & 0x200000)
>> 16) | ((text & 0x20000) >> 13) | ((text & 0x2000) >> 10) | ((text & 0x200) >> 7) | ((text & 0x20) >>
4) | ((text & 0x2) >> 1));
u8 num4 = (u8)(((text & 0x10000000) >> 21) | ((text & 0x1000000) >> 18) | ((text & 0x100000)
>> 15) | ((text & 0x10000) >> 12) | ((text & 0x1000) >> 9) | ((text & 0x100) >> 6) | ((text & 0x10) >>
3) | ((text & 0x1) ));
// f, g, h, k with karnau map and bit slicing
u8 f = (u8)((~(num1 | num2) & num4) | ((num1 | num2) & ~num4));
u8 g = (u8)((num1 & ~(num2 | num3)) | (~num1 & (num2 | num3)));
u8 h = (u8)(((~num1 | num2) & ~(num3 | num4)) | (~num2 & ((num1 & num4) | num3)));
u8 k = (u8)((num2 & ((~num1 & num3 & ~num4) | (num1 & ~num3))) | (~num3 & num4) |
(~(num1 | num2) & (~num3 | num4)));
output = (((u32)f << 24) | ((u32)g << 16) | ((u32)h << 8) | ((u32)k));
return output;
}
4. 최적화
기존 코드에서 p_box1_gen 함수는 32bit text 값을 각 bit 별 자리로 재정렬한 것이므로 s-box 연산에 사용하였던 비트슬라이싱을 활용하여 s-box 연산과 결합이 가능합니다.
또한 keygen 의 경우 32번 loop마다 동일한 constant 값을 얻을 수 있고, loop를 128, 64, 32, 16, 8, 4, 2, 1 번 돈다고 가정하였을 때 1번 loop에서 가장 최적화된 결과를 얻을 수 있습니다. constant의 경우 하드코딩을 통해 계산 과정을 없앴습니다.
이를 통한 최종 결론은 다음과 같습니다.
최종적으로 97.5% 성능이 향상된 결과를 얻었습니다.
5. 코드 및 후기
이번 문항을 통해 카르노맵과 비트슬라이싱에 대해 알 수 있어 좋았습니다. 시상식에 참석하니 6번 문항을 두 자리로 해결한 팀이 1등을 차지하였기에 6번 문항으로 1,2,3 등이 갈린 것 같았습니다. 저희 팀에 어셈블리를 할 줄 아는 사람이 없었어서 245ms 가 최상의 결과였지만, 제출 이틀 전인가 푼 결과로는 아주 만족했습니다.
코드는 다음과 같습니다.
#pragma GCC optimize ("-O3")
typedef unsigned char u8;
typedef unsigned short u16;
//typedef unsigned int u32;
// round: #128
#define NUM_ROUND 128
// key_gen constant
#define CONST_VAL 0xab00cd00
// rotation left
#define ROL(X) ((X<<1) | (X>>31))
// s_box: 4-bit x #16
u32 s_box[16] = {0x3, 0x9, 0x6, 0xf, 0xe, 0x5, 0xd, 0x4, 0xc, 0x7, 0xa, 0x2, 0xb, 0x1, 0x8, 0x0};
// key generation
void new_bs_keygen(u32* r_key, u32 m_key){
u32 m_key_table[4] = {m_key, m_key+32, m_key+64, m_key+96};
r_key[0] = m_key_table[0] ^ 0xAB00CD00;
r_key[32] = m_key_table[1] ^ 0xAB00CD00;
r_key[64] = m_key_table[2] ^ 0xAB00CD00;
r_key[96] = m_key_table[3] ^ 0xAB00CD00;
r_key[1] = ++m_key_table[0] ^ 0x56019A01;
r_key[33] = ++m_key_table[1] ^ 0x56019A01;
r_key[65] = ++m_key_table[2] ^ 0x56019A01;
r_key[97] = ++m_key_table[3] ^ 0x56019A01;
r_key[2] = ++m_key_table[0] ^ 0xAC033402;
r_key[34] = ++m_key_table[1] ^ 0xAC033402;
r_key[66] = ++m_key_table[2] ^ 0xAC033402;
r_key[98] = ++m_key_table[3] ^ 0xAC033402;
r_key[3] = ++m_key_table[0] ^ 0x58066805;
r_key[35] = ++m_key_table[1] ^ 0x58066805;
r_key[67] = ++m_key_table[2] ^ 0x58066805;
r_key[99] = ++m_key_table[3] ^ 0x58066805;
r_key[4] = ++m_key_table[0] ^ 0xB00CD00A;
r_key[36] = ++m_key_table[1] ^ 0xB00CD00A;
r_key[68] = ++m_key_table[2] ^ 0xB00CD00A;
r_key[100] = ++m_key_table[3] ^ 0xB00CD00A;
r_key[5] = ++m_key_table[0] ^ 0x6019A015;
r_key[37] = ++m_key_table[1] ^ 0x6019A015;
r_key[69] = ++m_key_table[2] ^ 0x6019A015;
r_key[101] = ++m_key_table[3] ^ 0x6019A015;
r_key[6] = ++m_key_table[0] ^ 0xC033402A;
r_key[38] = ++m_key_table[1] ^ 0xC033402A;
r_key[70] = ++m_key_table[2] ^ 0xC033402A;
r_key[102] = ++m_key_table[3] ^ 0xC033402A;
r_key[7] = ++m_key_table[0] ^ 0x80668055;
r_key[39] = ++m_key_table[1] ^ 0x80668055;
r_key[71] = ++m_key_table[2] ^ 0x80668055;
r_key[103] = ++m_key_table[3] ^ 0x80668055;
r_key[8] = ++m_key_table[0] ^ 0xCD00AB;
r_key[40] = ++m_key_table[1] ^ 0xCD00AB;
r_key[72] = ++m_key_table[2] ^ 0xCD00AB;
r_key[104] = ++m_key_table[3] ^ 0xCD00AB;
r_key[9] = ++m_key_table[0] ^ 0x19A0156;
r_key[41] = ++m_key_table[1] ^ 0x19A0156;
r_key[73] = ++m_key_table[2] ^ 0x19A0156;
r_key[105] = ++m_key_table[3] ^ 0x19A0156;
r_key[10] = ++m_key_table[0] ^ 0x33402AC;
r_key[42] = ++m_key_table[1] ^ 0x33402AC;
r_key[74] = ++m_key_table[2] ^ 0x33402AC;
r_key[106] = ++m_key_table[3] ^ 0x33402AC;
r_key[11] = ++m_key_table[0] ^ 0x6680558;
r_key[43] = ++m_key_table[1] ^ 0x6680558;
r_key[75] = ++m_key_table[2] ^ 0x6680558;
r_key[107] = ++m_key_table[3] ^ 0x6680558;
r_key[12] = ++m_key_table[0] ^ 0xCD00AB0;
r_key[44] = ++m_key_table[1] ^ 0xCD00AB0;
r_key[76] = ++m_key_table[2] ^ 0xCD00AB0;
r_key[108] = ++m_key_table[3] ^ 0xCD00AB0;
r_key[13] = ++m_key_table[0] ^ 0x19A01560;
r_key[45] = ++m_key_table[1] ^ 0x19A01560;
r_key[77] = ++m_key_table[2] ^ 0x19A01560;
r_key[109] = ++m_key_table[3] ^ 0x19A01560;
r_key[14] = ++m_key_table[0] ^ 0x33402AC0;
r_key[46] = ++m_key_table[1] ^ 0x33402AC0;
r_key[78] = ++m_key_table[2] ^ 0x33402AC0;
r_key[110] = ++m_key_table[3] ^ 0x33402AC0;
r_key[15] = ++m_key_table[0] ^ 0x66805580;
r_key[47] = ++m_key_table[1] ^ 0x66805580;
r_key[79] = ++m_key_table[2] ^ 0x66805580;
r_key[111] = ++m_key_table[3] ^ 0x66805580;
r_key[16] = ++m_key_table[0] ^ 0xCD00AB00;
r_key[48] = ++m_key_table[1] ^ 0xCD00AB00;
r_key[80] = ++m_key_table[2] ^ 0xCD00AB00;
r_key[112] = ++m_key_table[3] ^ 0xCD00AB00;
r_key[17] = ++m_key_table[0] ^ 0x9A015601;
r_key[49] = ++m_key_table[1] ^ 0x9A015601;
r_key[81] = ++m_key_table[2] ^ 0x9A015601;
r_key[113] = ++m_key_table[3] ^ 0x9A015601;
r_key[18] = ++m_key_table[0] ^ 0x3402AC03;
r_key[50] = ++m_key_table[1] ^ 0x3402AC03;
r_key[82] = ++m_key_table[2] ^ 0x3402AC03;
r_key[114] = ++m_key_table[3] ^ 0x3402AC03;
r_key[19] = ++m_key_table[0] ^ 0x68055806;
r_key[51] = ++m_key_table[1] ^ 0x68055806;
r_key[83] = ++m_key_table[2] ^ 0x68055806;
r_key[115] = ++m_key_table[3] ^ 0x68055806;
r_key[20] = ++m_key_table[0] ^ 0xD00AB00C;
r_key[52] = ++m_key_table[1] ^ 0xD00AB00C;
r_key[84] = ++m_key_table[2] ^ 0xD00AB00C;
r_key[116] = ++m_key_table[3] ^ 0xD00AB00C;
r_key[21] = ++m_key_table[0] ^ 0xA0156019;
r_key[53] = ++m_key_table[1] ^ 0xA0156019;
r_key[85] = ++m_key_table[2] ^ 0xA0156019;
r_key[117] = ++m_key_table[3] ^ 0xA0156019;
r_key[22] = ++m_key_table[0] ^ 0x402AC033;
r_key[54] = ++m_key_table[1] ^ 0x402AC033;
r_key[86] = ++m_key_table[2] ^ 0x402AC033;
r_key[118] = ++m_key_table[3] ^ 0x402AC033;
r_key[23] = ++m_key_table[0] ^ 0x80558066;
r_key[55] = ++m_key_table[1] ^ 0x80558066;
r_key[87] = ++m_key_table[2] ^ 0x80558066;
r_key[119] = ++m_key_table[3] ^ 0x80558066;
r_key[24] = ++m_key_table[0] ^ 0xAB00CD;
r_key[56] = ++m_key_table[1] ^ 0xAB00CD;
r_key[88] = ++m_key_table[2] ^ 0xAB00CD;
r_key[120] = ++m_key_table[3] ^ 0xAB00CD;
r_key[25] = ++m_key_table[0] ^ 0x156019A;
r_key[57] = ++m_key_table[1] ^ 0x156019A;
r_key[89] = ++m_key_table[2] ^ 0x156019A;
r_key[121] = ++m_key_table[3] ^ 0x156019A;
r_key[26] = ++m_key_table[0] ^ 0x2AC0334;
r_key[58] = ++m_key_table[1] ^ 0x2AC0334;
r_key[90] = ++m_key_table[2] ^ 0x2AC0334;
r_key[122] = ++m_key_table[3] ^ 0x2AC0334;
r_key[27] = ++m_key_table[0] ^ 0x5580668;
r_key[59] = ++m_key_table[1] ^ 0x5580668;
r_key[91] = ++m_key_table[2] ^ 0x5580668;
r_key[123] = ++m_key_table[3] ^ 0x5580668;
r_key[28] = ++m_key_table[0] ^ 0xAB00CD0;
r_key[60] = ++m_key_table[1] ^ 0xAB00CD0;
r_key[92] = ++m_key_table[2] ^ 0xAB00CD0;
r_key[124] = ++m_key_table[3] ^ 0xAB00CD0;
r_key[29] = ++m_key_table[0] ^ 0x156019A0;
r_key[61] = ++m_key_table[1] ^ 0x156019A0;
r_key[93] = ++m_key_table[2] ^ 0x156019A0;
r_key[125] = ++m_key_table[3] ^ 0x156019A0;
r_key[30] = ++m_key_table[0] ^ 0x2AC03340;
r_key[62] = ++m_key_table[1] ^ 0x2AC03340;
r_key[94] = ++m_key_table[2] ^ 0x2AC03340;
r_key[126] = ++m_key_table[3] ^ 0x2AC03340;
r_key[31] = ++m_key_table[0] ^ 0x55806680;
r_key[63] = ++m_key_table[1] ^ 0x55806680;
r_key[95] = ++m_key_table[2] ^ 0x55806680;
r_key[127] = ++m_key_table[3] ^ 0x55806680;
}
/*
u32 s_box_gen(u32 text){
u32 output = 0;
u32 temp = 0;
int i = 0;
for(i=0;i<8;i++){
temp = ( ( text >> (4*i) ) & 0x0000000F );
temp = s_box[temp];
output = (output | ( temp << (4*i) ) );
}
return output;
}
u32 p_box1_gen(u32 text){
u32 p_idx[32] = {0, 8, 16, 24, 1, 9, 17, 25, 2, 10, 18, 26, 3, 11, 19, 27, 4, 12, 20, 28, 5, 13, 21, 29, 6, 14, 22, 30, 7, 15, 23, 31};
u32 output = 0;
u32 temp = 0;
int i = 0;
for(i=0;i<32;i++){
temp = ((text>>i) & 0x00000001);
temp = (temp << p_idx[i]);
output = (output | temp);
}
return output;
}
u32 p_box2_gen(u32 text){
u32 p_idx[32] = {27, 1, 23, 30, 7, 22, 29, 16, 0, 4, 13, 18, 25, 17, 28, 31, 10, 14, 3, 5, 6, 2, 12, 11, 9, 8, 19, 26, 24, 20, 15, 21};
u32 output = 0;
u32 temp = 0;
int i = 0;
for(i=0;i<32;i++){
temp = ((text>>i) & 0x00000001);
temp = (temp << p_idx[i]);
output = (output | temp);
}
return output;
}
*/
void new_bs_enc(u32* r_key, u32* text){
int i;
u8 text1 = (u8)((*text) >> 24);
u8 text2 = (u8)((*text) >> 16);
u8 text3 = (u8)((*text) >> 8 );
u8 text4 = (u8)(*text);
u8 num1; u8 num2; u8 num3; u8 num4;
for(i = 0; i < NUM_ROUND; i+=4){
// sbox_gen with bit slicing
num1 = ((text1 & 0x80) | ((text1 & 0x08) << 3) | ((text2 & 0x80) >> 2) | ((text2 & 0x08) << 1) | ((text3 & 0x80) >> 4) | ((text3 & 0x08) >> 1) | ((text4 & 0x80) >> 6) | ((text4 & 0x08) >> 3));
num2 = (((text1 & 0x40) << 1) | ((text1 & 0x04) << 4) | ((text2 & 0x40) >> 1) | ((text2 & 0x04) << 2) | ((text3 & 0x40) >> 3) | (text3 & 0x04) | ((text4 & 0x40) >> 5) | ((text4 & 0x04) >> 2));
num3 = (((text1 & 0x20) << 2) | ((text1 & 0x02) << 5) | (text2 & 0x20) | ((text2 & 0x02) << 3) | ((text3 & 0x20) >> 2) | ((text3 & 0x02) << 1) | ((text4 & 0x20) >> 4) | ((text4 & 0x02) >> 1));
num4 = (((text1 & 0x10) << 3) | ((text1 & 0x01) << 6) | ((text2 & 0x10) << 1) | ((text2 & 0x01) << 4) | ((text3 & 0x10) >> 1) | ((text3 & 0x01) << 2) | ((text4 & 0x10) >> 3) | (text4 & 0x01) );
// f, g, h, k
text1 = ((~(num1 | num2) & num4) | ((num1 | num2) & ~num4));
text2 = ((num1 & ~(num2 | num3)) | (~num1 & (num2 | num3)));
text3 = (((~num1 | num2) & ~(num3 | num4)) | (~num2 & ((num1 & num4) | num3)));
text4 = ((num2 & ((~num1 & num3 & ~num4) | (num1 & ~num3))) | (~num3 & num4) | (~(num1 | num2) & (~num3 | num4)));
// add rkey_in
text1 ^= (u8)(r_key[i] >> 24);
text2 ^= (u8)(r_key[i] >> 16);
text3 ^= (u8)(r_key[i] >> 8);
text4 ^= (u8)(r_key[i]);
// pbox2_gen
num1 = ((text3 & 0x80) | ((text4 & 0x08) << 3) | ((text4 & 0x40) >> 1) | ((text3 & 0x40) >> 2) | ((text4 & 0x01) << 3) | ((text1 & 0x08) >> 1) | ((text3 & 0x10) >> 3) | ((text1 & 0x10) >> 4));
num2 = (((text4 & 0x04) << 5) | ((text4 & 0x20) << 1) | ((text1 & 0x80) >> 2) | ((text1 & 0x20) >> 1) | ((text1 & 0x04) << 1) | ((text3 & 0x08) >> 1) | ((text3 & 0x20) >> 4) | ((text4 & 0x80) >> 7));
num3 = (((text1 & 0x40) << 1) | ((text2 & 0x02) << 5) | ((text3 & 0x04) << 3) | ((text2 & 0x40) >> 2) | ((text2 & 0x80) >> 4) | ((text2 & 0x01) << 2) | ((text1 & 0x01) << 1) | ((text1 & 0x02) >> 1));
num4 = (((text4 & 0x10) << 3) | ((text2 & 0x10) << 2) | ((text2 & 0x08) << 2) | ((text3 & 0x02) << 3) | ((text2 & 0x04) << 1) | ((text2 & 0x20) >> 3) | (text4 & 0x02) | (text3 & 0x01));
text1 = num1;
text2 = num2;
text3 = num3;
text4 = num4;
//=======================================================
// sbox_gen
num1 = ((text1 & 0x80) | ((text1 & 0x08) << 3) | ((text2 & 0x80) >> 2) | ((text2 & 0x08) << 1) | ((text3 & 0x80) >> 4) | ((text3 & 0x08) >> 1) | ((text4 & 0x80) >> 6) | ((text4 & 0x08) >> 3));
num2 = (((text1 & 0x40) << 1) | ((text1 & 0x04) << 4) | ((text2 & 0x40) >> 1) | ((text2 & 0x04) << 2) | ((text3 & 0x40) >> 3) | (text3 & 0x04) | ((text4 & 0x40) >> 5) | ((text4 & 0x04) >> 2));
num3 = (((text1 & 0x20) << 2) | ((text1 & 0x02) << 5) | (text2 & 0x20) | ((text2 & 0x02) << 3) | ((text3 & 0x20) >> 2) | ((text3 & 0x02) << 1) | ((text4 & 0x20) >> 4) | ((text4 & 0x02) >> 1));
num4 = (((text1 & 0x10) << 3) | ((text1 & 0x01) << 6) | ((text2 & 0x10) << 1) | ((text2 & 0x01) << 4) | ((text3 & 0x10) >> 1) | ((text3 & 0x01) << 2) | ((text4 & 0x10) >> 3) | (text4 & 0x01) );
// f, g, h, k
text1 = ((~(num1 | num2) & num4) | ((num1 | num2) & ~num4));
text2 = ((num1 & ~(num2 | num3)) | (~num1 & (num2 | num3)));
text3 = (((~num1 | num2) & ~(num3 | num4)) | (~num2 & ((num1 & num4) | num3)));
text4 = ((num2 & ((~num1 & num3 & ~num4) | (num1 & ~num3))) | (~num3 & num4) | (~(num1 | num2) & (~num3 | num4)));
// add rkey_in
text1 ^= (u8)(r_key[1 + i] >> 24);
text2 ^= (u8)(r_key[1 + i] >> 16);
text3 ^= (u8)(r_key[1 + i] >> 8);
text4 ^= (u8)(r_key[1 + i]);
// pbox2_gen
num1 = ((text3 & 0x80) | ((text4 & 0x08) << 3) | ((text4 & 0x40) >> 1) | ((text3 & 0x40) >> 2) | ((text4 & 0x01) << 3) | ((text1 & 0x08) >> 1) | ((text3 & 0x10) >> 3) | ((text1 & 0x10) >> 4));
num2 = (((text4 & 0x04) << 5) | ((text4 & 0x20) << 1) | ((text1 & 0x80) >> 2) | ((text1 & 0x20) >> 1) | ((text1 & 0x04) << 1) | ((text3 & 0x08) >> 1) | ((text3 & 0x20) >> 4) | ((text4 & 0x80) >> 7));
num3 = (((text1 & 0x40) << 1) | ((text2 & 0x02) << 5) | ((text3 & 0x04) << 3) | ((text2 & 0x40) >> 2) | ((text2 & 0x80) >> 4) | ((text2 & 0x01) << 2) | ((text1 & 0x01) << 1) | ((text1 & 0x02) >> 1));
num4 = (((text4 & 0x10) << 3) | ((text2 & 0x10) << 2) | ((text2 & 0x08) << 2) | ((text3 & 0x02) << 3) | ((text2 & 0x04) << 1) | ((text2 & 0x20) >> 3) | (text4 & 0x02) | (text3 & 0x01));
text1 = num1;
text2 = num2;
text3 = num3;
text4 = num4;
//=======================================================
// sbox_gen
num1 = ((text1 & 0x80) | ((text1 & 0x08) << 3) | ((text2 & 0x80) >> 2) | ((text2 & 0x08) << 1) | ((text3 & 0x80) >> 4) | ((text3 & 0x08) >> 1) | ((text4 & 0x80) >> 6) | ((text4 & 0x08) >> 3));
num2 = (((text1 & 0x40) << 1) | ((text1 & 0x04) << 4) | ((text2 & 0x40) >> 1) | ((text2 & 0x04) << 2) | ((text3 & 0x40) >> 3) | (text3 & 0x04) | ((text4 & 0x40) >> 5) | ((text4 & 0x04) >> 2));
num3 = (((text1 & 0x20) << 2) | ((text1 & 0x02) << 5) | (text2 & 0x20) | ((text2 & 0x02) << 3) | ((text3 & 0x20) >> 2) | ((text3 & 0x02) << 1) | ((text4 & 0x20) >> 4) | ((text4 & 0x02) >> 1));
num4 = (((text1 & 0x10) << 3) | ((text1 & 0x01) << 6) | ((text2 & 0x10) << 1) | ((text2 & 0x01) << 4) | ((text3 & 0x10) >> 1) | ((text3 & 0x01) << 2) | ((text4 & 0x10) >> 3) | (text4 & 0x01) );
// f, g, h, k
text1 = ((~(num1 | num2) & num4) | ((num1 | num2) & ~num4));
text2 = ((num1 & ~(num2 | num3)) | (~num1 & (num2 | num3)));
text3 = (((~num1 | num2) & ~(num3 | num4)) | (~num2 & ((num1 & num4) | num3)));
text4 = ((num2 & ((~num1 & num3 & ~num4) | (num1 & ~num3))) | (~num3 & num4) | (~(num1 | num2) & (~num3 | num4)));
// add rkey_in
text1 ^= (u8)(r_key[2 + i] >> 24);
text2 ^= (u8)(r_key[2 + i] >> 16);
text3 ^= (u8)(r_key[2 + i] >> 8);
text4 ^= (u8)(r_key[2 + i]);
// pbox2_gen
num1 = ((text3 & 0x80) | ((text4 & 0x08) << 3) | ((text4 & 0x40) >> 1) | ((text3 & 0x40) >> 2) | ((text4 & 0x01) << 3) | ((text1 & 0x08) >> 1) | ((text3 & 0x10) >> 3) | ((text1 & 0x10) >> 4));
num2 = (((text4 & 0x04) << 5) | ((text4 & 0x20) << 1) | ((text1 & 0x80) >> 2) | ((text1 & 0x20) >> 1) | ((text1 & 0x04) << 1) | ((text3 & 0x08) >> 1) | ((text3 & 0x20) >> 4) | ((text4 & 0x80) >> 7));
num3 = (((text1 & 0x40) << 1) | ((text2 & 0x02) << 5) | ((text3 & 0x04) << 3) | ((text2 & 0x40) >> 2) | ((text2 & 0x80) >> 4) | ((text2 & 0x01) << 2) | ((text1 & 0x01) << 1) | ((text1 & 0x02) >> 1));
num4 = (((text4 & 0x10) << 3) | ((text2 & 0x10) << 2) | ((text2 & 0x08) << 2) | ((text3 & 0x02) << 3) | ((text2 & 0x04) << 1) | ((text2 & 0x20) >> 3) | (text4 & 0x02) | (text3 & 0x01));
text1 = num1;
text2 = num2;
text3 = num3;
text4 = num4;
//=======================================================
// sbox_gen
num1 = ((text1 & 0x80) | ((text1 & 0x08) << 3) | ((text2 & 0x80) >> 2) | ((text2 & 0x08) << 1) | ((text3 & 0x80) >> 4) | ((text3 & 0x08) >> 1) | ((text4 & 0x80) >> 6) | ((text4 & 0x08) >> 3));
num2 = (((text1 & 0x40) << 1) | ((text1 & 0x04) << 4) | ((text2 & 0x40) >> 1) | ((text2 & 0x04) << 2) | ((text3 & 0x40) >> 3) | (text3 & 0x04) | ((text4 & 0x40) >> 5) | ((text4 & 0x04) >> 2));
num3 = (((text1 & 0x20) << 2) | ((text1 & 0x02) << 5) | (text2 & 0x20) | ((text2 & 0x02) << 3) | ((text3 & 0x20) >> 2) | ((text3 & 0x02) << 1) | ((text4 & 0x20) >> 4) | ((text4 & 0x02) >> 1));
num4 = (((text1 & 0x10) << 3) | ((text1 & 0x01) << 6) | ((text2 & 0x10) << 1) | ((text2 & 0x01) << 4) | ((text3 & 0x10) >> 1) | ((text3 & 0x01) << 2) | ((text4 & 0x10) >> 3) | (text4 & 0x01) );
// f, g, h, k
text1 = ((~(num1 | num2) & num4) | ((num1 | num2) & ~num4));
text2 = ((num1 & ~(num2 | num3)) | (~num1 & (num2 | num3)));
text3 = (((~num1 | num2) & ~(num3 | num4)) | (~num2 & ((num1 & num4) | num3)));
text4 = ((num2 & ((~num1 & num3 & ~num4) | (num1 & ~num3))) | (~num3 & num4) | (~(num1 | num2) & (~num3 | num4)));
// add rkey_in
text1 ^= (u8)(r_key[3 + i] >> 24);
text2 ^= (u8)(r_key[3 + i] >> 16);
text3 ^= (u8)(r_key[3 + i] >> 8);
text4 ^= (u8)(r_key[3 + i]);
// pbox2_gen
num1 = ((text3 & 0x80) | ((text4 & 0x08) << 3) | ((text4 & 0x40) >> 1) | ((text3 & 0x40) >> 2) | ((text4 & 0x01) << 3) | ((text1 & 0x08) >> 1) | ((text3 & 0x10) >> 3) | ((text1 & 0x10) >> 4));
num2 = (((text4 & 0x04) << 5) | ((text4 & 0x20) << 1) | ((text1 & 0x80) >> 2) | ((text1 & 0x20) >> 1) | ((text1 & 0x04) << 1) | ((text3 & 0x08) >> 1) | ((text3 & 0x20) >> 4) | ((text4 & 0x80) >> 7));
num3 = (((text1 & 0x40) << 1) | ((text2 & 0x02) << 5) | ((text3 & 0x04) << 3) | ((text2 & 0x40) >> 2) | ((text2 & 0x80) >> 4) | ((text2 & 0x01) << 2) | ((text1 & 0x01) << 1) | ((text1 & 0x02) >> 1));
num4 = (((text4 & 0x10) << 3) | ((text2 & 0x10) << 2) | ((text2 & 0x08) << 2) | ((text3 & 0x02) << 3) | ((text2 & 0x04) << 1) | ((text2 & 0x20) >> 3) | (text4 & 0x02) | (text3 & 0x01));
text1 = num1;
text2 = num2;
text3 = num3;
text4 = num4;
}
*text = (((u32)text1 << 24) | ((u32)text2 << 16) | ((u32)text3 << 8) | (u32)text4);
}
u8 TEST_VECTOR(u32 in, u32 answer) {
return (in == answer);
}
void setup() {
Serial.begin(115200);
pinMode(LED_BUILTIN, OUTPUT);
// r_key : 32-bit x #128
u32 r_key[128] = {0, };
// m_key : 32-bit
u32 m_key[3] = {0x12345678,0x01020304,0x55667788};
// text: 32-bit
u32 text[3] = {0x90ABCDEF,0x0A0B0C0D,0xFFEEDDCC};
u32 out_text[3]= {0xE4DE2FF8,0xE7F54BDC,0x53485E4F};
Serial.println("-----------------");
Serial.println(" TEST VECTOR ");
Serial.println("-----------------");
for(int i=0; i<3; i++) {
new_bs_keygen(r_key, m_key[i]);
new_bs_enc(r_key, &text[i]);
if(TEST_VECTOR(text[i], out_text[i])){
Serial.println(">> CORRECT");
}else{
Serial.println(">> WRONG");
}
}
Serial.println("-----------------");
Serial.println(" BENCHMARK ");
Serial.println("-----------------");
// m_key : 32-bit
u32 m_key_bench = 0x12345678;
// text: 32-bit
u32 text_bench = 0x90ABCDEF;
u32 time1;
u32 time2;
time1 = millis();
for(int i=0; i<64; i++) {
new_bs_keygen(r_key, m_key_bench);
new_bs_enc(r_key, &text_bench);
}
time2 = millis();
Serial.print(">> ");
Serial.println((time2-time1));
Serial.println("-----------------");
}
void loop() {
}
'암호학 > 2021 암호경진대회' 카테고리의 다른 글
2021 암호분석경진대회 4번 풀이 (0) | 2021.11.23 |
---|---|
2021 암호분석경진대회 3번 풀이 (0) | 2021.11.22 |
2021 암호분석경진대회 소감 (6) | 2021.11.22 |