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

AttributeError排查:'bytes'对象无'oid'属性(P2MS脚本开发)

解决P2MS脚本中AttributeError: 'bytes' object has no attribute 'oid'错误

问题背景

开发P2MS功能脚本时,第14行触发AttributeError,提示'bytes' object has no attribute 'oid',尝试哈希对象后问题仍未解决,不清楚报错原因。

完整代码

from Crypto.PublicKey import DSA
from Crypto.Signature import DSS
import random
import os

def generate_dsa_key_pair(bits=1024):
    """Generates a DSA key pair with the given number of bits."""
    key = DSA.generate(bits)
    return key

def sign_text(text, key):
    """Signs the given text using the given DSA private key."""
    signer = DSS.new(key, 'fips-186-3')
    signature = signer.sign(text.encode())
    return signature

def create_p2ms_script(n, m):
    """Creates a P2MS script using the given number of public keys and signatures."""
    # Generate N DSA key pairs
    keys = [generate_dsa_key_pair() for i in range(n)]

    # Select M private keys from the N keys
    priv_keys = random.sample(keys, m)

    # Generate M signatures using the private keys
    signatures = [sign_text("help me", priv_key) for priv_key in priv_keys]

    # Create scriptPubKey by concatenating the N public keys
    scriptPubKey = b''.join([key.publickey().export_key(format='DER') for key in keys])

    # Create scriptSig by concatenating the M signatures
    scriptSig = b''.join(signatures)

    return scriptPubKey, scriptSig

def save_script_to_file(script, filename):
    """Saves the given script to the specified file."""
    with open(filename, 'wb') as f:
        f.write(script)

def execute_p2ms_script(scriptPubKey, scriptSig):
    """Executes the given P2MS script by verifying the signatures using the public keys."""
    # Split scriptPubKey into individual public keys
    pub_keys = [DSA.import_key(key) for key in scriptPubKey.split(b'\x00\x02\x81\x81') if key]

    # Split scriptSig into individual signatures
    signatures = [sig for sig in scriptSig.split(b'\x00\x02\x81\x81') if sig]

    # Check if the number of signatures matches the number of public keys
    if len(signatures) != len(pub_keys):
        return False

    # Verify each signature using the corresponding public key
    for i, sig in enumerate(signatures):
        verifier = DSS.new(pub_keys[i], 'fips-186-3')
        if not verifier.verify("help me ".encode(), sig):
            return False

    return True

if __name__ == '__main__':
    n = int(input("Enter the number of public keys (N): "))
    m = int(input("Enter the number of signatures (M): "))

    # Create P2MS script
    scriptPubKey, scriptSig = create_p2ms_script(n, m)

    # Save script

报错回溯

Exception has occurred: AttributeError
'bytes' object has no attribute 'oid'
File ", line 14, in sign_text signature = signer.sign(text.encode())
File , line 26, in <listcomp> signatures = [sign_text("help me", priv_key) for priv_key in priv_keys]
File , line 26, in create_p2ms_script signatures = [sign_text("help me", priv_key) for priv_key in priv_keys]
File , line 66, in <module> scriptPubKey, scriptSig = create_p2ms_script(n, m)
AttributeError: 'bytes' object has no attribute 'oid'

错误原因

DSS.sign()方法要求传入哈希对象(如SHA256实例),而非原始bytes数据。直接传入text.encode()(bytes类型)会导致内部逻辑尝试访问bytes对象不存在的oid属性,触发报错。

修复方案

1. 补充哈希模块导入

添加Crypto.Hash.SHA256导入,用于生成符合要求的哈希对象:

from Crypto.Hash import SHA256

2. 修改签名函数

将文本编码后转换为SHA256哈希对象,再传入签名方法:

def sign_text(text, key):
    """Signs the given text using the given DSA private key."""
    signer = DSS.new(key, 'fips-186-3')
    hash_obj = SHA256.new(text.encode())
    signature = signer.sign(hash_obj)
    return signature

3. 同步修正验证逻辑

验证时需使用与签名一致的哈希对象,同时修正原代码中文本不一致的问题(多了一个空格):

def execute_p2ms_script(scriptPubKey, scriptSig, m):
    """Executes the given P2MS script by verifying the signatures using the public keys."""
    # Split scriptPubKey into individual public keys
    pub_keys = [DSA.import_key(key) for key in scriptPubKey.split(b'\x00\x02\x81\x81') if key]

    # Split scriptSig into individual signatures
    signatures = [sig for sig in scriptSig.split(b'\x00\x02\x81\x81') if sig]

    # P2MS要求签名数M ≤ 公钥数N,修正原判断逻辑
    if len(signatures) != m:
        return False

    # Verify each signature using the corresponding public key
    for i, sig in enumerate(signatures):
        verifier = DSS.new(pub_keys[i], 'fips-186-3')
        hash_obj = SHA256.new("help me".encode())
        if not verifier.verify(hash_obj, sig):
            return False

    return True

4. 额外优化提示

原代码用固定字节串b'\x00\x02\x81\x81'拆分公钥和签名存在风险,DER格式的公钥可能包含该字节序列。建议改用长度前缀方式存储:每个公钥/签名前先写入4字节长度值,拆分时先读取长度再截取对应数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 22:21:01