[알고리즘] PIPO Masking 구현
0. Boolen masking 기본 설계
처음 구조는 다음과 같다. 키 스케줄링에서는 딱히 마스킹이 들어가지 않고 암호화 알고리즘 자체에서만 마스킹이 진행이 된다.
기본적인 개념은 위의 그림처럼 Plaintext를 Xor로 잘라서 각각의 Share로 만들어준다. 이 때, 기본적은 share은 두개이고 하나의 Share는 암호화 할때 항상 랜덤으로 하고 나머지 Share는 plaintext랑 연산을 해줘서 만든다. 동일하게 Roundkey도 plaintext과 동일하게 Share Group을 만든다.
그래서 원래는 Roundkey자체랑 Plaintext 자체 끼리 계산을 하는게 아니라 plain과 RK의 Share끼리 계산이 된다.
그 다음 S-layer를 거치게 되는데 여기서 bitslice로 구현되어 있는 것을 마스킹을 하기 위해서는 원래 구현되어 있는 것에 각각의 Share끼리 연산을 진행하게 된다.
이과정에서 마스킹이 들어 날 수 있기 때문에 기존의 마스킹을 새것으로 바꿔준다. 나중에 다시 state를 만들기 위해서는 share끼리 xor을 하면되는데, 이 때 각각의 Share끼리 And 연산을 하면, 원래의 state가 복구가 안되기 때문에 ISW_And를 새로 만들었다.
void ISW_AND(u8 *out , u8 *in1 , u8 *in2) {
int r1, r2;
for (int i = 0; i < SHARES; i++) {
out[i] = in1[i] & in2[i];
}
for (int i = 0; i < SHARES; i++) {
for (int j = i + 1; j < SHARES; j++) {
r1 = rand();
r2 = (r1 ^ (in1[i] & in2[j])) ^ (in1[j] & in2[i]);
out[i] ^= r1;
out[j] ^= r2;
}
}
}
처음에 share끼리 연산을 해주고, state가 다시 xor하면 state가 될수 있도록 뒤의 코드를 첨부했음
ISW_OR도 마찬가지
void ISW_OR(u8* out, u8* in1, u8* in2) {
ISW_AND(out, in1, in2);
for (int i = 0; i < SHARES; i++) {
out[i] ^= in1[i] ^ in2[i];
}
}
And 연산을 하고 state를 살려주기 위해서 share끼리 연산을 해준다.
그다음 R - layer는 Share를 shift해주면 된다.