合約アカウントには 3 つのサブタスクがあり、これらはすべて「bad account」シリーズを構成しています。この記事はシリーズの 3 番目のタスクである「Orderless Hashing」です。
分析#
この問題は前の問題と同様に 2 つのコントラクトがあり、アカウントコントラクト「GrandPharaoh」のコンストラクタで特定の公開鍵が指定されています。__validate__
内のget_multicall_hash
は、各 Call に対して再帰的にハッシュを計算し、最後に XOR 演算子 (^) を使用してハッシュを組み合わせます。ハッシュは u256 型で、low * high が最終的な messageHash です。私たちは、署名に渡すために r と s を構築する必要がありますが、これらは ECDSA で検証できるようになっています。
実行する必要がある Call は、別のコントラクトのRoyalSpear.equip(0)
ですが、これはアカウントコントラクト「GrandPharaoh」によってのみ呼び出すことができます。
秘密鍵がないため、ECDSA の脆弱性を見つけて解読する必要があります。
過程#
まず、Call リストの計算結果がどのようなものかを確認する必要があります。これは[equip(0)]
、[equip(1),equip(0)]
、またはそれ以上の値である必要がありますが、最後の値がequip(0)
である必要があります。
この部分は、cairo のテストを書くために snforge を使用して、アカウントコントラクトに(multicall_hash.low.into() * multicall_hash.high.into()).print();
を追加して読み取ることができます。
明らかに、[equip(0),equip(0)]
に対応するハッシュは 0 であることがわかります。これを利用して解決できます。
次に、check_ecdsa_signature
の詳細を調べて、具体的にどのように署名が検証されるかを確認します。
use ecdsa::check_ecdsa_signature;
をコメントアウトし、ソースコードをテストに貼り付けて、必要な場所に print を追加します。
まず、let zG: EcPoint = gen_point.mul(message_hash);
に注意します。message_hash が 0(無限の点)であるため、楕円曲線上で P*0=0 となります。したがって、zG は 0 です。以下のコードを使用して確認すると、'zG_x not exist' と出力されます。なぜなら、無限の点には x 座標が存在しないからです。
match zG.try_into() {
Option::Some(pt) => {
let (x, _) = ec::ec_point_unwrap(pt);
'zG_x'.print();
x.print();
},
Option::None => { 'zG_x not exist'.print(); },
};
コメントには、検証の式が(zG +/- rQ).x = sR.x
であることが明記されており、zG + rQ
に対応するコードは次のようになります:
match (zG + rQ).try_into() {
Option::Some(pt) => {
let (x, _) = ec::ec_point_unwrap(pt);
if (x == sR_x) {
return true;
}
},
Option::None => {},
};
ここで、zG は 0 なので、rQ.x = sR.x
が必要です。r は渡されたsigature.r
、Q は公開鍵に対応する曲線上の点、s は渡されたsigature.r
、R は r に対応する曲線上の点です。
明らかに、r=s かつ Q=R であれば、検証に合格します。公開鍵はブロックチェーンエクスプローラーのデプロイトランザクションから見つけることができます。
最後に、前の問題と同じ方法で、特定の署名と calls を Starknet.js の invokeFunction に渡してタスクを完了します。
結論#
ECDSA を深く学習し、楕円曲線の演算規則を知っていれば、この問題は非常に簡単に解決できます。コントラクトのマルチサイン設計は非常に単純であり、署名のリプレイ攻撃を利用することができます。
これでアカウントセクションの 3 つの問題がすべて解決されました。Cairo シリーズ全体には、Cairo で仮想マシンを書くものがありますが、私はそれをやるつもりはありません。アルゴリズム問題は嫌いです。将来的には、Starknet で実際に開発中に遭遇した興味深いものを更新する予定ですので、お楽しみに。