CS 문의에 출금 번호라고 적힌 값이 둘 있어서 withdrawals 를 id 로 그대로 조회했더니 아무것도 안 나왔다. deposits 와 trades 에서도 찾아봤지만 전부 0건이었다.
Table of contents
Open Table of contents
증상 — 조회로는 안 나오던 번호
번호 형식은 정상으로 보였고 자릿수도 그럴듯했다. 그런데 어느 테이블에서도 그 값을 키로 가진 행이 없었다.
application.yml 을 열어 보니 obfuscator.withdrawal·obfuscator.deposit·obfuscator.trade 로 식별자 공간마다 다른 multiplier 가 정의돼 있었다. 밖으로 나가는 번호는 내부 키가 아니라 IdObfuscator 가 그 곱수로 인코딩한 값이었다. 보안 검토 때 순번 노출을 막으려고 넣은 것이었다.
원인 — 공간마다 다른 파라미터 세트
문제는 어느 세트로 풀어야 하는지가 번호만 봐서는 안 나온다는 점이었다. 세트마다 결과가 전혀 다른 값으로 나온다.
두 가지 방법이 있었다. 화면 번호를 내부 id 로 되돌려 인코딩 자체를 없애는 것과, 후보 세트를 전부 풀어 보고 실재하는 행이 나오는 쪽을 채택하는 절차를 두는 것이다. 뒤쪽을 골랐다. 이유는 순번 노출을 막는 것이 보안 검토의 결정이라 우리가 되돌릴 사안이 아니어서다. 대신 문의마다 세 번 풀어 보는 수고를 감수했다. 값 자체로는 못 고르므로 존재 여부가 유일한 기준이었다.
틀려도 유효한 수가 나온다
이 인코딩의 성질이 판별을 어렵게 만들었다. 보통의 변환은 틀린 키로 풀면 깨진 값이 나와서 틀렸다는 것이 바로 보인다.
여기서는 곱셈 역원 inverse 로 푸는 방식이라 틀린 세트로 풀어도 그럴듯한 정수가 나오므로 틀린 것이 틀려 보이지 않는다. SELECT 1 FROM withdrawals WHERE id = ? 로 없다는 것을 확인하기 전까지는 맞는 값으로 보인다.
같은 문의의 다른 대상
풀어서 나온 두 값을 조회하니 둘 다 있었는데 서로 다른 출금이고 하나는 BTC 다른 하나는 ETH 였다. 재출금 문의라 원본과 재시도 건으로 짐작하고 있었다.
그 가정 때문에 초반 조사가 엉켰고 BTC 쪽 흐름으로 해석하다 ETH 데이터가 안 맞아 데이터가 이상하다고 봤다. 이상했던 것은 데이터가 아니라 두 번호가 같은 대상일 것이라는 가정이었다.
조치 — 상수를 외우지 않는 이유
절차를 정하면서 multiplier 를 메모에 적어 두고 쓰지 않기로 했다. 설정이 바뀌면 메모가 틀리고 틀린 값으로 풀어도 유효해 보이는 다른 수가 나온다.
그래서 application.yml 에서 그때그때 읽는다고 적었다. 문의에 적힌 번호는 각각 독립적으로 대상을 확정한 뒤에 관계를 확인한다는 것도 함께 남겼다.
정리
- 밖으로 나가는 번호가
IdObfuscator로 인코딩된 값일 수 있다 - 식별자 공간마다 다른
multiplier가 있다 - 세트가 틀려도 유효한 수가 나오므로 오류가 안 난다
- 틀린 것이 틀려 보이지 않으므로 존재 확인이 유일한 판별이다
- 후보 세트를 전부 풀어 실재하는 쪽을 고른다
- 파라미터는 메모하지 말고
application.yml에서 그때그때 읽는다 - 한 문의의 번호들이 같은 대상일 것이라 가정하지 않는다
- 각각 확정한 뒤에 관계를 확인한다