我正在开发一个项目,需要在 React 应用程序中生成 ECDSA 签名,然后在 Python 后端中验证它。签名生成和验证在各自的环境中工作,但是React中生成的签名在Python中验证失败。我在 React 中使用椭圆库,在 Python 中使用密码学库。
反应代码(签名生成):
import { useEffect } from 'react';
import { ec as EC } from 'elliptic';
const App = () => {
useEffect(() => {
const ec = new EC('secp256k1');
const private_key_hex = "cf63f7ffe346cd800e431b34bdbd45f6aac3c2ac6055ac18195753aff9b9cce8";
const message_hash_hex = "2f8fc7172db7dcbd71ec70c83263db33a54ff761b02a54480a8d07b9c633d651";
const privateKey = ec.keyFromPrivate(private_key_hex, 'hex');
const signature = privateKey.sign(message_hash_hex, 'hex', { canonical: true });
const signature_der_hex = signature.toDER('hex');
console.log("Signature (DER hex):", signature_der_hex);
}, []);
return <div><h1>ECDSA Signature in React</h1></div>;
};
export default App;
产量:
Signature (DER hex): 3045022100e5c678f346cdd180815912e580c27d9d70a4a2e71ab6cfb2bdaedfbf4cdf24cc02200bba6ae9b3bb25c886b5cc8549ac6796438f295e91320a1d705f17e25cb7199b
这是我尝试在 python 中验证签名的部分:
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.backends import default_backend
def verify_signature(public_key_hex, signature_der_hex, message_hash_hex):
public_key_bytes = bytes.fromhex(public_key_hex)
try:
public_key = ec.EllipticCurvePublicKey.from_encoded_point(ec.SECP256K1(), public_key_bytes)
except Exception as e:
print(f"Error loading public key: {e}")
return False
hashed_message = bytes.fromhex(message_hash_hex)
try:
signature_bytes = bytes.fromhex(signature_der_hex)
public_key.verify(signature_bytes, hashed_message, ec.ECDSA(hashes.SHA256()))
return True
except Exception as e:
print(f"Verification failed: {e}")
return False
public_key_hex = "03aa4fcbf0792ce77a3be9415bf96bff99a832466f56ecba3bb8ce630877de2701"
# Replace with signature from React
signature_der_hex = "3045022100e5c678f346cdd180815912e580c27d9d70a4a2e71ab6cfb2bdaedfbf4cdf24cc02200bba6ae9b3bb25c886b5cc8549ac6796438f295e91320a1d705f17e25cb7199b"
message_hash_hex = "2f8fc7172db7dcbd71ec70c83263db33a54ff761b02a54480a8d07b9c633d651"
verification_result = verify_signature(public_key_hex, signature_der_hex, message_hash_hex)
print("Verification:", verification_result)
问题: 当我在Python验证码中使用React应用程序生成的签名时,验证失败。但是,当我在每个环境中单独运行签名和验证过程时,它会成功。
我尝试过的:
我怀疑问题可能在于签名的编码方式或库处理 ECDSA 操作的一些细微差别。任何有关如何使这两种环境兼容的见解或建议将不胜感激。
与椭圆 NodeJS 库相比,pyca/cryptography Python 库隐式进行哈希处理。由于在这两种情况下都传递了哈希,因此一次哈希的消息在 NodeJS 代码中进行签名,但两次哈希的消息在 Python 代码中进行验证,这就是验证失败的原因。
为了使用 Python 进行验证成功,必须禁用隐式哈希,具体操作如下:
from cryptography.hazmat.primitives.asymmetric import utils
...
public_key.verify(signature_bytes, hashed_message, ec.ECDSA(utils.Prehashed(hashes.SHA256())))
通过此更改,使用Python代码验证成功。