시리얼 생성시 만족해야 할 조건 > 개발자팁

개발자팁

개발과 관련된 유용한 정보를 공유하세요.
질문은 QA에서 해주시기 바랍니다.

시리얼 생성시 만족해야 할 조건 정보

PHP 시리얼 생성시 만족해야 할 조건

본문

1. 연속된 번호로 생성될 확률이 작아야 한다.
2. 생성시 중복된 번호가 나올확률이 작아야 한다.
3. 알고리즘을 알고 있더라도 동일 시리얼을 만들어내기 어려워야 한다.
4. 사람이 쉽게 유추할수 있으면 안된다.
5. 우연히 아무렇게나 입력해도 맞을 확률이 낮아야 한다.

예를 들어
혜택이 많은 유료 서비스를 이용하기 위한 시리얼이라면
사람들이 충독적으로 숫자몇개를 더하고 빼서
유추될수 있으면 좋지 않은 시리얼 입니다.

웹에서 시리얼 번호를 받고 체크를 할시에
하루에 실패를 몇번 이상 하면 안된다하는 정도의 체크는 필수적으로 들어가야 합니다.
악의적으로 루프로 돌릴수도 있기 때문에 그렇습니다.


아래의 생성 함수에서는
$serial = str_replace('.', '', (string)bcmul(bcmul((float)$usec * 10000000 , (float)$sec) , get_rand_number(4)));
이것이 핵심인데
bcmul((float)$usec * 10000000 , (float)$sec)
자체로도 unique 한 숫자가 만들어집니다.
하지만 알고리즘을 알고있을시 충분히 악의적으로 생성할수 있는 가능성이 많습니다.
그래서 거기다가 다시 랜덤한 숫자를 곱해주는데
get_rand_number(4)
이것은 자리수가 높을수록 동일한 시리얼을 만들기 어려워집니다.
시리얼 생성 레벨 정도로 이해하시면 될듯합니다.
추천
1

댓글 3개

여기에도 '딴지'를 좀 걸겠습니다. ^^;

제가 유창화님 글에 '딴지'를 거는 이유는,
유창화님의 코드가, '난수발생'부분과 '시리얼코드화' 하는 부분이 섞여있는데
난수발생부분에서 사용하시는 방법 (본 글의 내용에 해당) 이
기존 난수발생기보다 낫다는 것을 인정할 수 없기 때문입니다.
(예를 들어, 위 코드의 리턴값은 항상 0으로 끝납니다. 그것도 가끔 여러개..
 물론, $usec에 곱하는 값을 한자리 낮추면 해결되기는 합니다만..)

저도 유창화님 글 이전에는 아무 생각없이 rand 써왔고,
유창화님 덕분에 php 난수발생기 부분에 대해서 더 이해를 할 수 있게 감사하게 생각하고 있습니다.
하지만, mt_rand라는 2^19937-1의 주기를 가진 '괜찮은' 난수발생기를 두고
( http://ko.wikipedia.org/wiki/%EB%A9%94%EB%A5%B4%EC%84%BC_%ED%8A%B8%EC%9C%84%EC%8A%A4%ED%84%B0 )
굳이 '검증되지 않은' 난수발생 방법을 사용해야 할 이유가 있는가 하는 것입니다.

제가 '검증되지 않았다'고 말씀드린 이유는,
유창화님이, (전체 시리얼키) 백만번 생성 중 반복이 발생하지 않았다고 하셨지만,
이는, 유창화님이 정리하신 '시리얼 생성시 조건' 중 2번만 해당하기 때문입니다.
(그리고, 제 실험에서는 10만번당 작은수(1~7)의 중복이 꾸준히 발견되었습니다.. 만 이는 서버나 라이브러리마다의 특성이라고 생각합니다.)
기존 난수발생기들은, 위와 같은 '시리얼 생성시 조건'과 비슷하거나 더 타이트한 조건에 맞게 설계되도록 되어있습니다. (그런데 rand 함수가 왜 그 모양인지는 모르겠네요..^^;)

마지막으로, 유창화님의 시리얼 생성시 조건 3번에 공감합니다.
즉, mt_rand 가 뛰어나다고 해도, 알려진 알고리즘보다는
기존 알고리즘에 한두 스텝을 더한 방법이 더 낫다고 생각합니다. ^^
정말 심도 있고 좋은 의견 감사합니다.

거기도 0을 하나 더 햇군요. 0을 하나 빼는게 맞습니다.
원래 정수로 만들고자 함인데 0을 하나 더 했군요......
감사합니다.

난수 발생기 부분은
엄밀하게 말하면 제가 만든 것은 완전한 난수 발생기가 아닙니다.

원래의 정확한 의도는
시간(microtime)은 계속해서 흐르기때문에
지난 시간 보다 작은 현재값이 현재에 나올수 없습니다.

또 거기다가 1000 이상의 4자리 숫자를 곱하기 때문에 이미 생성된 숫자가 나올수 없다는데 착안되어진 것입니다.
(지금은 조금 바뀌엇지만 원래 제가 의도한것은 이것입니다.)

마이크로타임 자체가 중복될수 없는 유니크한 값이므로 랜덤한 4자리 숫자를 곱할 필요는 없지만
앞자리 숫자를 유동적으로 출력하기 위함과 연번을 피하기 위해서 곱해진 것입니다.

아무튼 그러한 이유가 중복과 연번을 피하고자 함이 핵심입니다.

랜덤 함수는 말그대로 랜덤한 숫자를 만들어줄 뿐이지 매번 중복되지 않는 숫자를 만드는것은 아니기 때문에
전진님이 말한 그런 식의 방법은 사용하지 않은 것입니다.
랜덤 함수는 자릿수가 크면 클수록 그 확률은 줄어들겟지만
위에서 말한바와 같이 중복되거나 연번이 생성될 확률은 존재합니다.

제가 만든것이 mt_rand 보다 더 낫다는 그런뜻은 애초에 없었으며
또 용도가 다르므로 쓰지 않은 것이라는 점과
알고리즘 차원에서 이해해 주시면 좋겠습니다.



아무튼 좋은 의견 감사드립니다.
저도 많은 도움이 되었습니다.
네 ^^
저도 rand 함수나 mt_rand 함수 와 유창화님 코드를 비교할 생각은 없었습니다.
(근데 위 제 댓글을 보니 그런 느낌이.. 그랬다면 죄송합니다.)
유창화님 수준의 코드를 만들 수 있는 분들은 많지 않습니다. (저는 근처도 못가고요..^^;)
연번이나 중복이 거의 없으면서도, 난수 발생한번으로 16자리 키를 만드시는 코드는, 오랜 경험과 많은 지식에서 나온 훌륭한 코드라고 생각하고 있습니다.
아마 기존 난수발생기도 유창화님 코드와 비슷한 내부 알고리즘을 구현했을 거라고 생각합니다.

다시한번 공부거리를 주셔서 감사드리고 있습니다. ^^*
전체 64
개발자팁 내용 검색

회원로그인

(주)에스아이알소프트 / 대표:홍석명 / (06211) 서울특별시 강남구 역삼동 707-34 한신인터밸리24 서관 1404호 / E-Mail: admin@sir.kr
사업자등록번호: 217-81-36347 / 통신판매업신고번호:2014-서울강남-02098호 / 개인정보보호책임자:김민섭(minsup@sir.kr)
© SIRSOFT