本文へスキップ
ecdsa.com

low-S 正規化

ECDSA 署名の s の値が範囲の下半分(s ≤ n/2)になければならないとする規則で、ECDSA に本来備わっている署名の展性をなくすために Bitcoin と Ethereum が採用しました。
別表記low SLOW_Scanonical shigh-S

有効な ECDSA 署名 (r, s) に対しては、組 (r, n − s) も検証に通ります。nonce の符号を反転すると s の符号が反転する一方で、k·G と −k·G は x 座標が同じだからです。low-S は s ≤ n/2 を満たすほうを代表として選びます。署名者は、s がそれより大きい場合に s を n − s に置き換えて正規化します。secp256k1 では、n/2 の小数点以下を切り捨てた値は 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0 です。

BIP 146 に記載されているとおり、Bitcoin Core はバージョン 0.11.1(2015年)以降 low-S 署名だけを中継し、0.9.0 以降は low-S 署名を生成しています。libsecp256k1 の検証関数は high-S を拒否します。Ethereum の EIP-2(Homestead、2016年)は s が n/2 を超えるトランザクションを無効としましたが、ecrecover プリコンパイルは今も high-S の値を受け付けます。そのため、署名を検証するコントラクトは、この上限を自ら強制しなければなりません。

汎用の検証実装(OpenSSL、WebCrypto、Java、Go)は両方の形式を受け付けます。また、OpenSSL などの汎用の署名実装は正規化を行わないため、その署名の約半数は、正規化するまで low-S のチェックに通りません。EdDSA は、S が群の位数未満であることを求めることで、この問題を回避しています(RFC 8032 §5.1.7)。

規格と参考文献

すべての用語