本文へスキップ
ecdsa.com
Python cryptographyPython の cryptography

エラーメッセージ

Invalid EC key. Point is not on the curve specified.

cryptography 50.0 で再現しました。EllipticCurvePublicKey.from_encoded_point() は、同じ失敗を「Invalid EC key.」という、より簡潔なメッセージで報告します。ほかのスタックでは表現が異なり、OpenSSL 1.1 のエラースタックは「point is not on curve」と出力し、Node は JWK を「Invalid JWK EC key」で拒否しますが、その背後にある数学はどれも同じです。

Python cryptography — ValueError from EllipticCurvePublicNumbers.public_key()

このエラーの意味

指定した (x, y) の組は、指定した曲線の方程式 y² = x³ + ax + b (mod p) を満たしていません。ライブラリはインポート時にこれを検証します。曲線上にない点を受け入れると、秘密鍵が漏洩しうる無効曲線攻撃が可能になるためです。つまり、この拒否は安全のためのチェックであり、杓子定規な対応ではありません。このチェックは曲線の方程式を 1 回計算するだけの軽い処理で、まともなライブラリはどれもこれを実行します。曲線上にない点はどこかで必ず拒否されるので、後段の処理で拒否されるよりも、ここではっきりと拒否されるほうが望ましいのです。

発生する理由

修正方法

  1. 1.

    エンコードされた点から、正しい曲線を指定して鍵を構築する

    from_encoded_point は長さと構造を一度に検証します。元のデータがどちらの曲線のものか曖昧な場合は、もう一方の候補の曲線も試してください。

    python
    from cryptography.hazmat.primitives.asymmetric import ec
    
    point = b"\x04" + x_bytes + y_bytes          # uncompressed, 65 bytes for P-256
    key = ec.EllipticCurvePublicKey.from_encoded_point(ec.SECP256R1(), point)
    # if that raises, test: ec.SECP256K1() — the other 256-bit suspect
  2. 2.

    元になる値を確認する

    鍵を構築する前に、長さが 32 バイトであることと、値が妥当であることを確認してください。削除されたゼロは、左側をゼロでパディングして復元してください。

    python
    print(len(x_bytes), len(y_bytes))        # must be 32, 32 for P-256
    x_bytes = x_bytes.rjust(32, b"\x00")     # repair stripped leading zeros
    y_bytes = y_bytes.rjust(32, b"\x00")

関連するエラー

署名エラーデータベースをすべて見る