Python ECDSA问题:使用secp224k1曲线私钥签名SHA-224摘要遇阻
Hey there, let's work through the common issues you might be facing when using the Python ECDSA module with secp224k1, SHA-224 digests for both private key material and signed data. This combination has a few less-documented gotchas, so let's break them down step by step:
1. Ensure secp224k1 is properly supported
Many Python ECDSA libraries don't include secp224k1 by default (it's not a NIST standard curve), so you may need to define its parameters explicitly if the library doesn't have it built-in. Here's how to do that:
from ecdsa import curves, SigningKey, VerifyingKey # Explicitly define secp224k1 curve parameters secp224k1 = curves.CurveFp( p=0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D, a=0x00000000000000000000000000000000000000000000000000000000, b=0x00000000000000000000000000000000000000000000000000000005, g=(0xA1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C, 0x7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5), n=0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661C2CA1F5B923081AA5ED, h=1 )
If your library does have secp224k1 built-in, you can skip this and just use curves.secp224k1 directly.
2. Fix your SHA-224-derived private key
A raw 28-byte SHA-224 digest might be larger than secp224k1's order (n). ECDSA requires private keys to be integers between 1 and n-1, so you need to take the digest modulo n to get a valid private key:
import hashlib # Generate SHA-224 digest from your private key material private_key_input = b"your_private_key_seed_here" sha224_digest = hashlib.sha224(private_key_input).digest() # Convert digest to integer and clamp it to the curve's order private_key_int = int.from_bytes(sha224_digest, byteorder='big') % secp224k1.order # Create a valid SigningKey from the clamped integer sk = SigningKey.from_secret_exponent(private_key_int, curve=secp224k1)
Skipping this step will almost certainly result in an invalid private key error.
3. Avoid double-hashing when signing the SHA-224 digest
Most ECDSA implementations automatically hash input data with a specified function. If you're passing a pre-computed SHA-224 digest, you must tell the library not to re-hash it—otherwise you'll sign a hash of your hash, which will never verify:
# Generate SHA-224 digest of the data you want to sign data_to_sign = b"your_actual_data_here" data_sha224 = hashlib.sha224(data_to_sign).digest() # Sign the pre-hashed digest (disable automatic hashing) signature = sk.sign(data_sha224, hashfunc=None)
4. Match verification steps to signing steps
When verifying the signature, use the same pre-hashed digest and disable automatic hashing to keep things consistent:
# Get the verifying key from your signing key vk = sk.get_verifying_key() # Verify the signature try: vk.verify(signature, data_sha224, hashfunc=None) print("Signature verified successfully!") except Exception as e: print(f"Verification failed: {str(e)}")
5. Double-check byte order
Always use big-endian (byteorder='big') when converting between bytes and integers—this is the cryptography standard. Mismatched byte order will lead to invalid keys or signatures, so explicitly specify it when using int.from_bytes() or .to_bytes().
If you're still hitting errors, share the exact error message you're getting (e.g., ValueError: Invalid private key or VerificationError) along with a minimal snippet of your code. That will help narrow down the issue even faster.
内容的提问来源于stack exchange,提问作者jsstuball

