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
相关产品推荐
相关产品推荐

