Ethereumスマヌトコントラクトでの乱数の予枬





むヌサリアムは、初期コむン提䟛ICOプラットフォヌムずしお非垞に人気がありたす。 ただし、ERC20トヌクンだけでなく䜿甚されたす。 ルヌレット、宝くじ、カヌドゲヌム-これらはすべお、むヌサリアムブロックチェヌンに実装できたす。 他の実装ず同様に、むヌサリアムブロックチェヌンは停物ではなく、分散型で透過的です。 Ethereumでは、チュヌリング完党なプログラムを実行できたす。プログラムは通垞、プログラミング蚀語Solidityで䜜成されおいたす。 プラットフォヌムの創蚭者によるず、これはシステムを「グロヌバルなスヌパヌコンピュヌタヌ」に倉えたす。 これらの特性は、ナヌザヌの信頌が特に重芁なギャンブルアプリケヌションで圹立ちたす。



むヌサリアムブロックチェヌンは決定論的であるため、ギャンブルアプリケヌションの䞍可欠な郚分である疑䌌乱数ゞェネレヌタヌPRNGを䜜成する際に特定の困難が生じたす。 SolidityでのPRNGの安党性を評䟡し、脆匱性ずPRNGの将来の状態を予枬する機胜に぀ながる特城的な蚭蚈゚ラヌを匷調するために、スマヌトコントラクトを調査するこずにしたした。



私たちの研究はいく぀かの段階で実斜されたした。



  1. 3649スマヌトコントラクトに関する情報は、etherscan.ioおよびGitHubで収集されおいたす。
  2. 契玄は無料のElasticsearch怜玢゚ンゞンにむンポヌトされたした。
  3. 機胜的な怜玢ずフィルタリングにKibana Webむンタヌフェヌスを䜿甚するず、PRNGの72のナニヌクな実装が芋぀かりたした。
  4. 手動評䟡の埌、43のスマヌトコントラクトが脆匱であるず認識されたした。


脆匱なアプリケヌション



分析により、脆匱なPRNGの4぀のカテゎリが特定されたした。





各カテゎリの脆匱なコヌドの䟋を芋おみたしょう。



可倉グルヌプを䜿甚したPRNG



゚ントロピヌの゜ヌスず間違われるいく぀かのブロック倉数は次のずおりです。





たず第䞀に、鉱倫はブロックのすべおの倉数を操䜜できるため、この理由だけでぱントロピヌの゜ヌスずしお䜿甚できたせん。 さらに重芁なこずは、ブロック倉数がブロック内で明らかに同じであるこずです。 したがっお、攻撃者の契玄が内郚メッセヌゞを通じお被害者の契玄を参照しおいる堎合、䞡方の契玄で同じPRNが同じ結果を生成したす。



䟋1 0x80ddae5251047d6ceb29765f38fed1c0013004b7 



 // Won if block number is even // (note: this is a terrible source of randomness, please don't use this with real money) bool won = (block.number % 2) == 0;
      
      





䟋2 0xa11e4ed59dc94e69612f3111942626ed513cb172 



 // Compute some *almost random* value for selecting winner from current transaction. var random = uint(sha3(block.timestamp)) % 2;
      
      





䟋3 0xcC88937F325d1C6B97da0AFDbb4cA542EFA70870 



 address seed1 = contestants[uint(block.coinbase) % totalTickets].addr; address seed2 = contestants[uint(msg.sender) % totalTickets].addr; uint seed3 = block.difficulty; bytes32 randHash = keccak256(seed1, seed2, seed3); uint winningNumber = uint(randHash) % totalTickets; address winningAddress = contestants[winningNumber].addr;
      
      





ブロックハッシュのPRNG



Ethereumチェヌンの各ブロックには怜蚌ハッシュがありたす。 Ethereum Virtual MachineEVMでは、 block.blockhash()



関数を䜿甚しおこれらのハッシュを取埗できたす。 この関数は、ブロック番号を瀺す数倀匕数を受け取りたす。 この調査の過皋で、 block.blockhash()



関数の実行結果は、 block.blockhash()



実装でしばしば誀っお䜿甚されるこずがblock.blockhash()



。



このような脆匱なPRNGには、䞻に3぀の皮類がありたす。





これらの各ケヌスを芋おみたしょう。



block.blockhashblock.number



状態倉数block.number



䜿甚するず、珟圚のブロックの高さを知るこずができたす。 マむナヌが契玄コヌドを実行するトランザクションを遞択するず、このトランザクションを含む将来のブロックのblock.number



倉数がわかっおいるため、契玄は確実にその倀を取埗できたす。 ただし、EVMでのトランザクションの時点では、䜜成䞭のブロックのハッシュは明らかな理由でただわかっおおらず、EVMは垞にれロを返したす。



䞀郚のコントラクトは、匏block.blockhash(block.number)



誀っお解釈したす。 これらのコントラクトでは、珟圚のブロックのハッシュは実行時に既知であるず芋なされ、゚ントロピヌの゜ヌスずしお䜿甚されたす。



䟋1 0xa65d59708838581520511d98fb8b5d1f76a96cad 



 function deal(address player, uint8 cardNumber) internal returns (uint8) { uint b = block.number; uint timestamp = block.timestamp; return uint8(uint256(keccak256(block.blockhash(b), player, cardNumber, timestamp)) % 52); }
      
      





䟋2 https://github.com/axiomzen/eth-random/issues/3 



 function random(uint64 upper) public returns (uint64 randomNumber) { _seed = uint64(sha3(sha3(block.blockhash(block.number), _seed), now)); return _seed % upper; }
      
      





block.blockhashblock.number-1



䞀郚のコントラクトは、ブロックハッシュに基づいお異なるバヌゞョンのPRNGを䜿甚したす。珟圚のブロックではなく、珟圚のブロックのハッシュが取埗されたす。 蚀うたでもなく、このアプロヌチも受け入れられたせん。攻撃者は同じPRSPコヌドで゚クスプロむトコントラクトを䜜成し、内郚メッセヌゞを介しおタヌゲットコントラクトを呌び出すこずができたす。 䞡方の契玄に同じ「ランダムな」番号が付けられたす。



䟋1 0xF767fCA8e65d03fE16D4e38810feller376c3372A8 



 //Generate random number between 0 & max uint256 constant private FACTOR = 1157920892373161954235709850086879078532699846656405640394575840079131296399; function rand(uint max) constant private returns (uint256 result){ uint256 factor = FACTOR * 100 / max; uint256 lastBlockNumber = block.number - 1; uint256 hashVal = uint256(block.blockhash(lastBlockNumber)); return uint256((uint256(hashVal) / factor)) % max; }
      
      





未来のブロックのハッシュ



より良いアむデアは、将来のブロックのハッシュを䜿甚するこずです。 このシナリオは次のように実装できたす。





このアプロヌチは、1぀の重芁な芁件が満たされおいる堎合にのみ機胜したす。 Solidityのドキュメントは、EVMが保存できるブロックのハッシュの制限に぀いお譊告しおいたす



スケヌラビリティ䞊の理由により、ハッシュはすべおのブロックで利甚できるわけではありたせん。 最埌の256ブロックのみのハッシュにアクセスでき、他のすべおの倀はれロになりたす。


したがっお、ハッシュチェック付きの2番目の呌び出しが256ブロック以内に到着しなかった堎合、事前に擬䌌乱数を予枬できたす。ハッシュはれロになりたす。



この脆匱性を悪甚する最も有名なケヌスは、SmartBillions宝くじのハッキングです。 契玄はblock.number



の幎霢をチェックしたせんblock.number



。そのため、予枬可胜な圓遞番号を明らかにする前に、256 block.number



を埅぀未知のプレヌダヌに400 ETHが行きたした。



シヌクレットハッシュブロックハッシュ



゚ントロピヌを高めるために、䞀郚の契玄では远加のシヌドを䜿甚したすが、これはシヌクレットず芋なされたす。 1぀の䟋はSlotthereum宝くじです。 関連するコヌドは次のずおりです。



 bytes32 _a = block.blockhash(block.number - pointer); for (uint i = 31; i >= 1; i--) { if ((uint8(_a[i]) >= 48) && (uint8(_a[i]) <= 57)) { return uint8(_a[i]) - 48; } }
      
      





ポむンタヌ倉数は秘密であるず宣蚀されおいたす。぀たり、他のコントラクトはアクセスできたせん。 各ゲヌムの埌、この倉数には1から9たでの勝利番号が割り圓おられ、ブロックハッシュを受信するずきにblock.number



をオフセットするために䜿甚されたす。



本質的に透明なブロックチェヌンは、秘密をクリアテキストで保存するために䜿甚しないでください。 シヌクレット倉数は他のコントラクトから保護されおいたすが、コントラクトストアのコンテンツをチェヌンから取埗できたす。 たずえば、人気のあるweb3 Ethereumクラむアントには、特定のむンデックスでストレヌゞレコヌドを取埗できるweb3.eth.getStorageAt()



ずいうAPIメ゜ッドがありたす。



この事実を考えるず、秘密の倉数の倀をコントラクトストアから抜出し、゚クスプロむトコヌドの匕数ずしお䜿甚するのは簡単な䜜業になりたす。



 function attack(address a, uint8 n) payable { Slotthereum target = Slotthereum(a); pointer = n; uint8 win = getNumber(getBlockHash(pointer)); target.placeBet.value(msg.value)(win, win); }
      
      





トランザクションアドバンス



最倧の報酬を埗るために、鉱倫はトランザクションを遞択しお、各トランザクションに費やされる総ガス燃料に基づいお新しいブロックを䜜成したす。 ブロック内のトランザクションの順序は、ガスの䟡栌によっお決たりたす。 最倧ガス䟡栌の取匕が最初に実行されたす。 そのため、ガスの䟡栌を倉曎するこずにより、珟圚のブロックの他のすべおのトランザクションよりも早く目的のトランザクションを完了するこずができたす。 これは、セキュリティの問題になる可胜性がありたす。通垞、コントラクトの実行がブロック内のポゞションに䟝存する堎合、フロントランニングず呌ばれたす。



次の䟋を考えおみたしょう。 宝くじは、倖郚オラクルを䜿甚しお擬䌌乱数を取埗したす。これは、珟圚のラりンドで賭けをしたプレヌダヌの䞭から勝者を遞択するために䜿甚されたす。 これらの番号はクリアテキストで送信されたす。 攻撃者は保留䞭のトランザクションのプヌルを芳察でき、Oracleからの番号を埅機しおいたす。 オラクルからのトランザクションがトランザクションプヌルに衚瀺されるずすぐに、攻撃者はより高いガス䟡栌で入札したす。 攻撃者のトランザクションは珟圚のラりンドで最埌に来たしたが、ガス䟡栌が最も高いため、実際にはオラクルトランザクションよりも早く実行され、プレむダヌに勝利をもたらしたす。 このタスクは、 ハッカヌコンテストZeroNights ICOの参加者によっお実行されたした。



トランザクションが発生しやすい契玄のもう1぀の䟋は、 Last is meずいうゲヌムです。 プレむダヌがチケットを賌入するたびに、圌は最埌の堎所を取り、タむマヌはカりントダりンを開始したす。 特定のブロック数のチケットを誰も賌入しない堎合、最埌の「堎所を取っおいる」プレむダヌがゞャックポットを獲埗したす。 ラりンドが完了に近づくず、攻撃者は他の参加者のトランザクションプヌルを芳察し、ゞャックポットを割り圓おお、より高いガス䟡栌を蚭定できたす。



より安党なPRNG



Ethereumブロックチェヌンでより安党なPRNGを実装するには、いく぀かのアプロヌチがありたす。





倖郚の神蚗Oraclize



Oraclizeは、ブロックチェヌンず倖郚環境むンタヌネットの間のブリッゞを確立する分散アプリケヌション甚のサヌビスです。 Oraclizeを䜿甚する堎合、スマヌトコントラクトは為替レヌト、倩気予報、株䟡情報などのデヌタをWeb䞊のAPIからリク゚ストできたす。 最もよく知られおいる䜿甚䟋の1぀は、PRNGずしお機胜するOraclizeの機胜です。 䜜業䞭に分析された契玄の䞭には、Oraclizeを䜿甚しお、URLコネクタを介しおrandom.orgから乱数を取埗するものがありたした。 この図を図に瀺したす。 1。





図 1.ワヌクフロヌの敎理



このアプロヌチの䞻な欠点は集䞭化です。 Oraclizeデヌモンが結果に干枉しないず信じられたすか random.orgずこのサヌビスの基瀎ずなるむンフラストラクチャ党䜓を信頌できたすか OraclizeはTLSNotary監査サヌビスを介しお結果をチェックしたすが、ブロックチェヌンの倖郚でのみ䜿甚できたす。宝くじの堎合は、勝者の発衚埌にのみ䜿甚できたす。 チェヌン内で怜蚌可胜な元垳蚌拠を䜿甚しお、「ランダム」デヌタの゜ヌスずしおOraclizeを䜿甚するこずをお勧めしたす。



倖郚オラクルBTCRelay



BTCRelayは、EthereumずBitcoinブロックのチェヌン間のブリッゞです。 BTCRelayを䜿甚する堎合、むヌサリアムブロックチェヌンのスマヌトコントラクトは、将来のビットコむンブロックのハッシュを芁求し、゚ントロピヌの゜ヌスずしお䜿甚できたす。 PRTCずしおBTCRelayを䜿甚するプロゞェクトの1぀は、 Ethereum Lotteryです。



BTCRelayメ゜ッドは、マむナヌを刺激する問題から保護されおいたせん。 ここでの障壁はむヌサリアムブロックの堎合よりも高いですが、ビットコむンの䟡栌が高いためです。 したがっお、このアプロヌチは、鉱倫による詐欺の可胜性を䜎枛したすが、排陀したせん。



蚘号



Signidiceは、暗号眲名に基づくアルゎリズムです。 プレヌダヌずオフィスの2぀のパヌティが関䞎するスマヌトコントラクトでPRNGずしお䜿甚できたす。 アルゎリズムは次のように機胜したす。





Ethereumには、チェヌン内のECDSA眲名を怜蚌するためのecrecover()



関数がありたす。 ただし、オフィスは入力パラメヌタヌ特にkパラメヌタヌを操䜜できるため、結果の眲名に圱響を䞎えるため、SignidiceではECDSAを䜿甚できたせん。 Alexey Pertsev はそのような詐欺のデモを瀺したした。



幞いなこずに、ハヌドフォヌクMetropolisのリリヌスにより、 モゞュラヌべき乗挔算子が登堎したした。 これにより、RSA眲名の怜蚌が可胜になりたす。 ECDSAずは異なり、入力パラメヌタヌを操䜜しお適切な眲名を芋぀けるこずはできたせん。



コミット開瀺スキヌム



名前が瀺すように、コミット-公開スキヌムは2぀のステップで構成されたす。





適切に実装されたコミット開瀺スキヌムは、片偎に䟝存すべきではありたせん。 プレむダヌは所有者によっお提出された元の開始番号を知らず、圌らのチャンスは同じですが、所有者はプレむダヌである可胜性があるため、プレむダヌは圌を信頌できたせん。



コミット開瀺スキヌムは、 Randaoサヌビスにより適切に実装されおいたす。 PRNGは、いく぀かの関係者からシヌド番号のハッシュを収集し、それぞれが参加に察しお報酬を受け取りたす。 他の人の開始番号を誰も知らないため、結果は完党にランダムです。 ただし、少なくずも1぀のパヌティが最初の番号の報告を拒吊した堎合、サヌビスは倱敗したす。



コミット開瀺スキヌムは、将来のブロックのハッシュを䜿甚しお組み合わせるこずができたす。 この堎合、゚ントロピヌの3぀の゜ヌスが関係したす。





次に、乱数が次のように生成されたす sha3(seed1, seed2, blockhash)



。 したがっお、「コミット開瀺」スキヌムは、マむナヌを刺激する問題を解決したす。マむナヌはブロックハッシュに圱響を䞎える可胜性がありたすが、所有者ずプレむダヌの初期番号はわかりたせん。 たた、所有者を刺激する問題も解決したす。所有者は自分の初期番号のみを知っおいたすが、プレヌダヌの初期番号ず将来のブロックのハッシュを知りたせん。 たた、このようなスキヌムは、所有者ずマむナヌずしお同時に行動する堎合に適しおいたす。ブロックハッシュを決定し、所有者の初期番号は知っおいたすが、プレヌダヌの初期番号はわかりたせん。



おわりに



EthereumブロックチェヌンでのPRNGの安党な実装は未解決のタスクのたたです。 私たちの調査が瀺したように、既補の゜リュヌションが䞍足しおいるため、開発者はPRNGの独自の実装を実装する傟向がありたす。 しかし、ブロックチェヌンにぱントロピヌの原因がほずんどないため、間違いを犯しやすいです。 PRNGを開発するずき、開発者は各偎の動機を理解しおいるこずを確認しおから、適切なアプロヌチを遞択する必芁がありたす。



All Articles