hashid로 난독화하여 id 노출하지 않기
이번에 회사에서 개발하는 기능 중 하나가
인증 절차는 필요하지만 + 빡센 인증은 아니여도 됨
이라는 요구사항이 있었는데 이 때 알게된 hashid에 대해 써보았습니다
난독화
- 의도적으로 읽기 힘들게 만드는 것
- 예:
10
이라는 사용자 아이디를 ->"D439fhdsE"
로 난독화하면 원래 값인10
을 알아내기 어려움
- 예:
- 난독화 !== 암호화
- 암호화는 brute-force attack 등의 공격에도 매우 안전해야하지만
- 난독화는 그정도는 보안은 아님
hashids
- 난독화 오픈 소스
- 최근에 sqids (opens in a new tab)로 리브랜딩함
제공하는 기능
- non-negative integers -> string 으로 인코딩 / 디코딩
// 간단한 예시
// 왠만한 언어로 동일 구현되어있음
const sqids = new Sqids()
const id = sqids.encode([1, 2, 3]) // "86Rf07"
const numbers = sqids.decode(id) // [1, 2, 3]
- 길이 / 커스텀 스트링을 이용할 수 있는 기능도 있음
hashids를 사용하는 경우
-
어떤 정보를 노출하고 싶지는 않지만 + 완전히 숨기기는 힘들 때
- 반디부디를 예시로 들면, 인생지도 URL이
/home/13
이면 13번째 사용자임을 알 수 있음 - 난독화를 통해
/home/13
->/home/D439fhdsE
으로 사용자의 ID를 난독화할 수 있음 - 이 경우, 서비스의 규모가 밝혀지고 싶지 않을 때 난독화할 수 있을 듯 (근데 URL이 못생김)
- 반디부디를 예시로 들면, 인생지도 URL이
-
보안 문제 / 웹 스크래핑 등의 가능성을 줄이기 위해
/home/13
으로 접근 가능하다면/home/14
로도 임의 접근이 가능함
-
UUID가 너무 긴 경우
- 임의 생성 때문에 UUID를 고려했지만, 너무 길어서 어려웠던 경우의 사례
- hashids를 사용하면 길이를 지정해줄 수 있음
hashids를 사용하지 않는 경우
- negative interger의 경우 사용할 수 없음
- 보안
- 보안을 뚫었을 때 비용 vs 뚫는 비용을 고려해볼 때, 보안이 매우 중요하지 않는 경우만 사용하는게 좋을 듯
비슷한 대안
- Base64 encode
- 값을 숨기지 않고 문자로만 바꾸고 싶을 때 괜찮을 듯
- 회사 개발자분이 라이브러리 설치를 싫어하셔서 이걸 강력 주장하셨다
- uuid, nanoid
- 충돌 가능해도 괜찮고 + 디코딩이 안되도 괜찮을 때 적절할듯
- optimus, feistel cipher
- 숫자 -> 숫자 매핑을 원할 때