.. 이것으로 해결된줄 알았는데 다른 문제가 있다. 있지. 그럼. 대충 만든건 문제가 생긴다니까.
이번 버전의 문제점은 앞 부분이 동일할때 같은 문제가 생긴다는거다.
전체 스트링을 앞에서부터 암호화하면서 키를 변경하는 구조이기 때문에, 당연히 블럭 범위에 해당하는 앞 부분이 같아지면 해당 블럭의 암호화 결과는 동일해진다.
# ./test
000000000000000A TEA
Binery Dump Start :
DD 90 AD 30 FA 0A B5 F3 3C 14 01 32 7A FD 72 B3 :
000000000000000A TEA, DECRYPT
000000000000000A 3DES
Binery Dump Start :
8F 3F A6 BA 61 FA 06 CE 97 81 13 D3 A7 91 6F C3 :
000000000000000A 3DES, DECRYPT
000000000000000B TEA
Binery Dump Start :
DD 90 AD 30 FA 0A B5 F3 AF C2 F1 56 A2 EA 43 CE :
000000000000000B TEA, DECRYPT
000000000000000B 3DES
Binery Dump Start :
8F 3F A6 BA 61 FA 06 CE 21 B4 3F 44 A4 D5 4D 74 :
000000000000000B 3DES, DECRYPT
#
요런 결과가 나오게 된다. 그러니까 TEA 결과와 3DES 결과의 상위 8byte 결과는 같게 된다.
아. 이래서 3DES를 사용하려고 했던 거군. (이제 와서 짐작인거냐; 이건, 정당화?) EDE 구조에서 D는 버퍼를 역으로 따라가면서 암호화를 해주면 해결될 것 같다. 다른 지점이 가장 앞에 있을때는 첫번째 Encrypt에서 키를 다 바꿔줄거고, 다른 지점이 중간과 끝에 있을때는 첫번째 Encrypt에서 반쯤 섞어준 뒤에 두번째 Decrypt에서 모두 섞어줄거다.
섞는 것으로만 최적화를 한다면 EDE에서 세번째 E를 빼도 될듯. (되나?)
일단 tea로 string를 encrypt / decrypt하는 함수에 reverse 버전을 추가.
void tea_r_encrypt(char *dst, char *src, int len, const unsigned long long *key)
{
int __len = (len + 7) >> 3;
int i;
unsigned long long __key[2] = { *key, *(key + 1) };
for (i = __len - 1; i >= 0; i--) {
__tea_encrypt((((unsigned int *)dst) + (i << 1)), (((unsigned int *)src) + (i << 1)), (unsigned int *)__key);
__key[0] ^= *((unsigned long long *)((unsigned int *)dst + (i << 1)));
__key[1] ^= *((unsigned long long *)((unsigned int *)dst + (i << 1)));
}
}
void tea_r_decrypt(char *dst, char *src, int len, const unsigned long long *key)
{
int __len = (len + 7) >> 3;
int i;
unsigned long long __key1[2] = { *key, *(key + 1) };
unsigned long long __key2[2];
for (i = __len - 1; i >= 0; i--) {
__key2[0] = __key1[0] ^
*((unsigned long long *)((unsigned int *)src + (i << 1)));
__key2[1] = __key1[1] ^
*((unsigned long long *)((unsigned int *)src + (i << 1)));
__tea_decrypt((((unsigned int *)dst) + (i << 1)), (((unsigned int *)src) + (i << 1)), (unsigned int *)__key1);
__key1[0] = __key2[0];
__key1[1] = __key2[1];
}
}
그런 후에 3des의 중간 함수를 reverse 함수로 변경.
inline void tea_3des_encrypt(char *dst, char *src, int len, const unsigned long long *key1, const unsigned long long *key2, const unsigned long long *key3)
{
tea_encrypt(dst, src, len, key1);
tea_r_decrypt(src, dst, len, key2);
tea_encrypt(dst, src, len, key3);
}
inline void tea_3des_decrypt(char *dst, char *src, int len, const unsigned long long *key1, const unsigned long long *key2, const unsigned long long *key3)
{
tea_decrypt(dst, src, len, key3);
tea_r_encrypt(src, dst, len, key2);
tea_decrypt(dst, src, len, key1);
}
결과는?
# ./test
000000000000000A TEA
Binery Dump Start :
DD 90 AD 30 FA 0A B5 F3 3C 14 01 32 7A FD 72 B3 :
000000000000000A TEA, DECRYPT
000000000000000A 3DES
Binery Dump Start :
BC D5 32 82 62 99 20 BA 31 F5 75 E1 B7 57 0F A1 :
000000000000000A 3DES, DECRYPT
000000000000000B TEA
Binery Dump Start :
DD 90 AD 30 FA 0A B5 F3 AF C2 F1 56 A2 EA 43 CE :
000000000000000B TEA, DECRYPT
000000000000000B 3DES
Binery Dump Start :
D7 45 39 E4 BA 0E 5D 87 C7 E4 F7 B8 DB 82 DA 76 :
000000000000000B 3DES, DECRYPT
#
TEA의 두 결과는 앞 8byte 부분이 동일하지만, 3DES의 앞 8byte 결과는 나름 잘 분산되어 있다.