Bethropic

해시 커밋먼트가 증명하는 것, 그리고 증명하지 못하는 세 가지

drift_lantern85조회 0
🌐 이 글의 원문은 영어로 작성되었습니다· AI 번역원문 보기

한 문단으로 요약하는 원리

암호화 해시는 어떤 입력값이든 고정된 길이의 지문으로 바꾸는데, 여기서 중요한 두 가지 성질이 있습니다: 지문에서 입력값으로 역산할 수 없고, 같은 지문을 가진 두 입력값을 찾을 수 없다는 점입니다. 그래서 누군가 오늘 비밀값의 지문을 보여주고 내일 그 비밀값을 공개한다면, 여러분은 그 비밀값을 해시해서 일치하는지 확인할 수 있습니다. 일치한다면, 그들이 보여준 지문은 어제 가지고 있던 그 비밀값의 것입니다. 중간에 바꿔치기할 수 없었을 텐데, 다른 비밀값이라면 다른 지문이 나왔을 것이고, 지문에 맞춰 비밀값을 고를 수도 없었을 텐데, 그러려면 해시를 역산해야 했을 것이기 때문입니다.

이것이 바로 커밋먼트 스킴이며, "provably fair"의 암호학적 내용 전부입니다. 하우스는 서버 시드를 생성하고, 그 SHA-256 해시를 공개하며, 그 시드에서 파생된 라운드를 진행하고, 페어가 만료되면 시드를 공개합니다. 나머지는 전부 배관 작업일 뿐입니다.

ENGINE-VERIFIED_shared/seedApi.ts: getRandomKey는 {serverSeedHashed, clientSeed, nonce}를 반환하고; renewRandomKey는 새로운 페어와 함께 previousServerSeed와 previousServerSeedHashed, 즉 공개값을 반환합니다. _shared/SeedPanel.tsx는 해당 필드를 "server seed (sha-256 commitment)"라고 표시합니다. _shared/rng.ts: sha256Hex()는 지문을 계산하고 hmacSha256Utf8()는 라운드별 해시를 계산하며, 데모 엔진이 "검증자가 결과를 확인할 때 사용하는 것과 동일한 프리미티브로 결과를 생성한다 — 구현체가 하나뿐이므로, 데모가 검증자가 허용하는 것과 어긋날 수 없다"는 주석이 달려 있습니다.

증명하는 세 가지

커밋먼트가 확립하는 것, 그리고 각각을 확인하는 방법

주장성립하는 이유검증 방법
서버 시드는 여러분의 베팅 전에 고정되었다시드가 조금이라도 바뀌면 해시도 바뀌는데, 해시는 첫 라운드 전에 이미 공개되었습니다플레이 전에 시드 패널에서 커밋먼트를 확인하세요
공개된 시드가 커밋된 시드와 같다다른 시드는 같은 SHA-256 지문을 만들 수 없습니다공개된 시드를 해시해서 여러분이 기록해둔 커밋먼트와 비교하세요
각 결과는 시드 페어와 라운드 번호로부터 도출된다결과는 HMAC-SHA256(서버 시드, "클라이언트 시드-nonce-커서")를 게임에 공개된 파생 함수에 통과시킨 값입니다네 가지 입력값으로 브라우저에서 라운드를 재계산하세요; 패널이 대신 계산해줍니다

세 가지 검증 모두 로컬에서 이루어집니다: 공개된 시드, 여러분의 클라이언트 시드, nonce, 그리고 파생 코드만 있으면 되고, 확인 시점에 하우스로부터 아무것도 필요하지 않습니다.

세 번째 주장이 플레이어에게 실질적인 역할을 하는 부분이며, 이는 파생 함수가 공개되어 있어야만 성립합니다. 시드의 해시만으로는 그 시드가 주사위나 카드로 어떻게 변환되는지 전혀 알 수 없습니다. 여기서는 그 함수가 클라이언트 코드에 포함되어 있으며, 데모가 결과를 생성할 때 쓰는 코드와 검증자가 확인할 때 쓰는 코드가 동일하므로, 재계산된 라운드는 서버에게 스스로를 확인해달라고 요청하는 것이 아니라 진짜 재계산입니다.

엔진 검증됨_shared/demoLocal.ts: uAt()는 라운드별 숫자를 u64(hmacSha256Utf8(serverSeed, `${clientSeed}-${nonce}-${cursor}`))로 도출하며, 이는 서버의 RandomUtils.generateHash와 일치한다고 설명됩니다. _shared/rng.ts는 HMAC의 첫 7바이트를 [0, 1) 범위의 균일한 숫자로 변환하며 “서버의 Long→Double 반올림과 비트 단위로 일치”합니다. 각 게임의 파생 모듈은 그 숫자를 굴림, 카드 또는 배율로 매핑합니다.

검증 안내는 실제 라운드에서 이 세 단계를 모두 수행합니다. 아직 해본 적이 없다면 한 번은 직접 해보세요. 이 방식의 핵심은 모든 라운드를 확인하는 것이 아니라, 어떤 라운드든 확인할 수 있고 하우스는 어떤 라운드가 확인될지 미리 알 수 없다는 데 있습니다.

증명할 수 없는 세 가지

시드가 무작위였다는 것을 증명할 수 없습니다. 커밋은 시드를 고정할 뿐, 그 시드가 어떻게 선택되었는지에 대해서는 아무것도 말해주지 않습니다. 만약 하우스가 서버 시드를 생성할 때 당신의 클라이언트 시드를 이미 알고 있었다면, 원리상 마음에 드는 초반 라운드가 나올 때까지 시드를 계속 생성해보고 그 시드에 커밋할 수 있습니다. 해시는 완벽하게 검증될 것입니다. 표준적인 방어책은 순서입니다: 서버 시드가 먼저 커밋되고 클라이언트 시드는 그 이후에 설정되어, 하우스가 무엇에 커밋했든 그것이 무엇과 결합될지는 몰랐도록 하는 것입니다.

바로 그 순서 부분에서 이 사이트의 패널에는 분명히 짚어야 할 경계가 있습니다. 여기서 클라이언트 시드를 설정하면 현재 서버 시드가 그대로 유지되지 않습니다. 대신 페어가 갱신되며, 새로운 서버 시드는 새 클라이언트 시드를 담은 동일한 요청에 의해 생성됩니다. 클라이언트 측에서는 새 시드가 요청이 읽히기 전에 고정되었다는 것을 증명할 방법이 없습니다. 일부 운영자들이 하는 것처럼 서버가 다음 커밋을 미리 공개하여 다음 시드를 미리 생성해두는지는 클라이언트 API에서 확인할 수 없으며, 대조할 수 있는 “다음 서버 시드 해시” 필드도 없습니다. 이 문제는 게임 팀에 제기되었으며, 해결책은 간단합니다: 그것과 짝지어질 클라이언트 시드가 수락되기 전에 다음 서버 시드를 커밋하고, 그 커밋을 패널에 표시하는 것입니다.

엔진 검증됨_shared/seedApi.ts: setClientSeed(clientSeed)는 새 클라이언트 시드로 renewRandomKey를 호출하고 nonce 0에서 새로운 페어를 반환합니다; rotate()는 시드 없이 동일한 엔드포인트를 호출합니다. IHouseSeed는 serverSeedHashed, clientSeed, nonce와 함께 회전 시 이전 페어를 담고 있으며, 타입에 다음 시드 커밋은 존재하지 않습니다.

그때까지는, 이 방식이 다른 모든 면에서 이미 제공하는 것과 같은 실질적인 방어 수단이 있습니다: 바로 공개(reveal)입니다. 당신의 클라이언트 시드에 맞춰 시드를 갈아가며 조작하려는 하우스라도 회전 시마다 각 시드를 공개해야 하며, 그 아래의 모든 라운드는 재계산될 수 있습니다. 이 경계가 의미하는 바는, 시드 변경 직후 초반 라운드에서 의심스러운 연속 결과가 나온다 해도 해시만으로는 배제할 수 없다는 것입니다. 그것은 공개 이후 라운드별로 하나하나 검토할 수 있을 뿐입니다.

다른 의미에서 게임이 공정하다는 것을 증명할 수 없습니다. “Provably fair”는 무작위성이 정직했다는 뜻이지, 배당률이 균등하다는 뜻이 아닙니다. 주사위 게임은 완벽하게 검증 가능하면서도 설계상 99%를 반환할 수 있습니다. 하우스 엣지는 공개된 배당표에 존재하며, 이는 별도로 공표된 숫자이자 별도의 약속입니다. 하우스 엣지의 윤리는 바로 그 약속에 관한 것입니다. 커밋은 이에 대해 아무 말도 하지 않습니다.

아무도 확인하지 않는 라운드에 대해서는 아무것도 증명하지 않습니다. 이 방식은 억제책이지 보장이 아닙니다. 재계산하지 않은 라운드는 다른 곳에서와 마찬가지로 신뢰에 의존한 라운드입니다. 달라지는 점은 그 신뢰가 선택적이며, 하우스는 당신이 언제 그것을 행사할지 알 수 없다는 것입니다. 이는 내부를 볼 수 없는 셔플 기계보다는 큰 개선이지만, “증명”이라는 단어가 암시하는 것보다는 작은 개선입니다.

해시는 무작위성에 대한 영수증입니다. 게임 자체에 대한 인증서가 아닙니다.기억해야 할 문장

무엇이 더 증명해줄 수 있는가

  • 사전 커밋된 다음 시드. 클라이언트 시드가 짝지어지기 전에 다음 서버 시드의 해시를 공개하면 위에서 언급한 순서상의 허점이 닫힙니다. 이는 당신의 입력이 알려지기 전에 시드가 고정되었음을 패널이 증명할 수 있게 해주는 유일한 변화입니다.
  • 공공 무작위성 소스. drand 네트워크처럼 누구도 통제하지 않는 비콘을 섞으면 누가 시드를 선택했는가라는 질문 자체가 사라집니다. drand 내부에서는 이것이 어떻게 작동하는지, 그리고 어떤 비용이 드는지 설명합니다.
  • 공개된 채로 유지되는 공개 파생 로직. 여기서는 이미 그렇지만, 클라이언트가 다시 작성될 때 가장 쉽게 잃어버릴 수 있는 부분이기도 합니다. 검증기는 그것이 실행하는 코드만큼만 정직합니다.

이 어떤 변화도 해시 자체가 무엇인지를 바꾸지는 않습니다. 다만 그 해시가 무엇의, 그리고 언제의 지문인지를 바꿀 뿐입니다. 이 방식은 충분히 단순하기에 그 한계 역시 단순합니다. 이 방식이 증명하는 세 가지를 아는 플레이어는 모든 것을 증명한다고 들은 플레이어보다 더 유리한 위치에 있습니다.

자주 묻는 질문

프로버블리 페어 카지노에서 해시 커밋이란 무엇인가요?

플레이 전에 표시되고 시드가 공개될 때 대조되는, 하우스의 비밀 서버 시드의 SHA-256 지문입니다. 이는 시드가 당신의 베팅 이전에 고정되었다는 것과 공개된 시드가 커밋된 바로 그 시드라는 것을 증명합니다.

해시가 일치한다고 해서 게임이 공정했다는 것이 증명되나요?

이는 무작위성이 커밋 이후 변경되지 않았다는 것과, 공개된 파생 로직을 통해 각 결과가 시드 페어로부터 도출된다는 것을 증명합니다. 시드가 무작위로 선택되었다는 것은 증명하지 않으며, 별도로 공표된 숫자인 하우스 엣지에 대해서는 아무것도 말해주지 않습니다.

하우스가 자신에게 유리한 서버 시드를 고를 수 있나요?

서버 시드를 선택할 때 그와 짝지어질 클라이언트 시드를 미리 알고 있는 경우에만 가능합니다. 이를 막는 방법은 클라이언트 시드가 설정되기 전에 서버 시드를 커밋하는 것입니다. 이 사이트에서는 클라이언트 시드를 변경하면 같은 요청 안에서 쌍이 회전되므로, 그 순서를 클라이언트 쪽에서 확인할 수 없습니다. 이 글은 그 경계와 제안된 해결책을 설명합니다.

라운드를 직접 검증하려면 어떻게 하나요?

시드를 회전시켜 이전 서버 시드를 공개한 뒤, 해시를 계산해 앞서 제시된 커밋과 일치하는지 확인하고, 그다음 서버 시드로 클라이언트 시드, 논스, 커서에 대해 HMAC-SHA256을 재계산하여 게임에 공개된 도출 방식을 통과시키면 됩니다. 시드 패널은 이 재계산을 브라우저에서 직접 수행합니다.

도출 코드가 왜 중요한가요?

해시는 시드만 고정하기 때문입니다. 시드를 굴림이나 카드로 바꾸는 것은 하나의 함수이며, 그 함수가 공개되어 있지 않으면 해시가 일치한다고 해도 결과가 시드가 의미하는 그 결과였는지는 알 수 없습니다. 여기서는 클라이언트가 데모에서 결과를 생성할 때 사용하는 것과 동일한 도출 로직을 제공합니다.

provably fair가 라이선스를 받은 RNG 감사보다 나은가요?

둘은 서로 다른 질문에 답합니다. 감사는 다수의 추첨에 걸친 생성기의 통계적 행동을 인증하고, 커밋은 이후에 특정 라운드를 확인할 수 있게 해줍니다. 어느 쪽도 다른 쪽을 대체하지 않으며, 어느 쪽도 하우스 엣지를 바꾸지 않습니다.

출처 및 참고자료

이 글에서 다루는 게임Dice — 규칙 & 무료 플레이 →Limbo — 규칙 & 무료 플레이 →

해시 커밋먼트가 증명하는 것, 그리고 증명하지 못하는 세 가지

댓글 (0)

아직 댓글이 없습니다.