파이썬의 랜덤 함수 중 random.Random().getrandbits 를 쓸 때는 주의해야 될거에요.
일단 '32의 배수' 단위로 쓰지 마세요.
그리고 31, 30 등 32보다 약간 작은 숫자도 쓰지 마세요.
파이썬의 랜덤 함수 구조는 이래요.
메르센 트위스트 라고도 하는데, 그 구조를 이용해요.
624번 어떤 랜덤 테이블을 쓰는데, 이를 state라고 불러요.
http://svn.python.org/view/python/trunk/Modules/_randommodule.c?view=markup
소스를 참고하면 알 수 있어요.
getrandbits 함수는 genrand_int32 라는 함수로 32비트 단위로 숫자를 불러와요.
만약 getrandbits(32)를 쓴다면.. :( 그 수가 그대로 나오네요!
genrand_int32는 이렇게 리턴해요.
y = mt[self->index++]; y ^= (y >> 11); y ^= (y << 7) & 0x9d2c5680UL; y ^= (y << 15) & 0xefc60000UL; y ^= (y >> 18); return y;
네, y를 구할 수 있겠죠?
mt가 저희가 볼수도 있고 지정할 수도 있는 state값이에요.
getstate, setstate로 불러오고 지정할 수 있어요.
소스를 보다 보면, 처음에 랜덤 함수를 호출하고 그 다음 624번 getrandbits(32)를 자신이 호출한다면 state값을 알아낼 수 있다는 것을 알 수 있어요.
물론 64도 마찬가지겠죠? 분리하면 되거든요.
그래서 이 값을 getrandbits에서 리틀 엔디안 형식으로 저장해요.
그 다음 그걸 정수로 만들죠.
그러니 그러지 마셔요!
이 문제가 30c3 ctf guess 라는 100점짜리 문제로 나왔는데, 구글에 'python getrandbits attack' 이라고 치면 나올거에요.
별개로, random 함수는 6~7번 오른쪽으로 시프트한 값을 실수연산해서 쓰기 때문에 공격이 잘 될지는 모르겠네요, 대신 브루트포스 범위가 엄청 줄어들긴 하겠죠.