You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React与Python跨环境ECDSA签名验证失败问题排查

跨环境ECDSA签名验证问题:React(elliptic库)与Python(cryptography库)不兼容

问题背景

开发项目时遇到异常:React应用通过elliptic库生成ECDSA签名,Python后端用cryptography库验证失败,但各自环境内单独执行签名与验证均正常。

React签名生成代码

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;

生成的签名:

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)

已尝试操作

  • 确认两端消息哈希完全一致
  • React端将签名转为DER格式后发送
  • 对齐React与Python的公钥格式

问题原因与解决方案

核心问题

差异出在签名输入的处理逻辑:

  • elliptic库的sign方法传入'hex'格式哈希时,直接将hex解码为字节后签名,不会再次哈希。
  • Python cryptography库默认会对传入的hashed_message再次执行SHA256哈希,导致验证时使用的哈希值与签名时不一致。

修复方案

修改Python验证代码,启用预哈希验证模式,告诉库传入的消息已经是哈希后的结果:

# 替换原verify调用部分
public_key.verify(
    signature_bytes,
    hashed_message,
    ec.ECDSA(hashes.SHA256(), prehashed=True)  # 关键参数:prehashed=True
)

完整修复后的Python代码:

from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives import hashes

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(), prehashed=True))
        return True
    except Exception as e:
        print(f"Verification failed: {e}")
        return False

public_key_hex = "03aa4fcbf0792ce77a3be9415bf96bff99a832466f56ecba3bb8ce630877de2701"
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)

内容的提问来源于stack exchange,提问作者Muppet

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 22:05:22