React 和 Python 之间跨环境 ECDSA 签名验证失败

问题描述 投票:0回答:1

我正在开发一个项目,需要在 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应用程序生成的签名时,验证失败。但是,当我在每个环境中单独运行签名和验证过程时,它会成功。

我尝试过的:

  • 确保消息哈希在两个环境中相同。
  • 在将签名发送到 Python 之前,在 React 中将签名转换为 DER 格式(按照上面的代码)
  • 在 React 和 Python 之间调整公钥格式。

我怀疑问题可能在于签名的编码方式或库处理 ECDSA 操作的一些细微差别。任何有关如何使这两种环境兼容的见解或建议将不胜感激。

javascript python reactjs cryptography ecdsa
1个回答
0
投票

与椭圆 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代码验证成功。

© www.soinside.com 2019 - 2024. All rights reserved.