引发 ValueError("无效的 DER 输入:数据不足") ValueError:无效的 DER 输入:数据不足如何解决这个错误

问题描述

我正在尝试在我的区块链项目中使用 ED25519 签署和验证区块链交易,但我得到了一个

ValueError "无效的 DER 输入:数据不足

当我添加 encode_dss_signature 和 decode_dss_signature 时。

我首先将数据转换为 json 格式,然后将其编码为 (utf-8) 格式。然后当我尝试使用 decode_dss_signature 解码签名时。它给出了上述值错误

import json
import uuid 
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
from cryptography.hazmat.primitives.asymmetric.utils import(
    encode_dss_signature,decode_dss_signature
)

from cryptography.exceptions import InvalidSignature
from cryptography.hazmat.primitives import serialization

class Wallet:
    """
    An individual wallet for a miner.
    Keeps track of the miners's balance.
    Allows a miner to authorize transactions.
    """
    def __init__(self):
        self.address = str(uuid.uuid4())[0:8] 
        self.private_key = Ed25519PrivateKey.generate()
        self.public_key = self.private_key.public_key()
        self.serialize_public_key()

    def sign(self,data):
        """
        Generate a signature based on the data using the local private key.
        """
        return decode_dss_signature(self.private_key.sign(
            json.dumps(data).encode('utf-8')
        ))


    def serialize_public_key(self):
        """
        Reset the public key to its serialized version.
        """
        self.public_key = self.public_key.public_bytes(
            encoding=serialization.Encoding.PEM,format=serialization.PublicFormat.SubjectPublicKeyInfo
        ).decode('utf-8')

        print(f'\n-- self.public_key: {self.public_key}')


    @staticmethod
    def verify(public_key,signature,data):
        """
        Verify signature based on original public_key and data.
        """

        deserialized_public_key = serialization.load_pem_public_key(
            public_key.encode('utf-8')
        )

        print(f'\n--signature: {signature}\n')
        (r,s) = signature

        try:
            deserialized_public_key.verify(
                encode_dss_signature(r,s),json.dumps(data).encode('utf-8')
            )

            return True

        except InvalidSignature:
            return False


def main():
    wallet = Wallet()
    print(f'wallet.__dict__: {wallet.__dict__}')

    data = { 'foo':'bar' }

    signature = wallet.sign(data)
    print(f'signature: {signature}')

    sign_verification = Wallet.verify(wallet.public_key,data)
    print(f'sign_verification: {sign_verification}')

   sign_verify_Failed = Wallet.verify(Wallet().public_key,data)
   print(f'sign_verify_Failed: {sign_verify_Failed}')

if __name__ == '__main__':
    main()

解决方法

我在测试中发现,根据 private_key 生成的 Ed25519PrivateKey,我最终得到了不同的错误。

通过简单地按照发布的程序运行 10,000 次,我得到了以下所有 ValueError 类型:

值错误信息 出现次数 出现百分比
无效的DER输入:数据不足 7193 71.93%
无效的DER输入:意外的标签 2389 23.89%
无效的DER输入:意外的高标签号 334 3.34%
无效的DER输入:DER中不允许不定长形式 39 0.39%
无效的 DER 输入:长度未最低编码 31 0.31%
无效的DER输入:尾随数据 14 0.14%

您可以自己尝试:

from collections import Counter


def main():
    c = Counter()
    for i in range(10_000):
        try:
            wallet = Wallet()
            data = { 'foo':'bar' }
            wallet.sign(data)
        except ValueError as e:
            c.update([str(e)])
    print(c)

虽然,cryptography.hazmat.primitives.asymmetric.utils.decode_dss_signature(signature) 理论上

接收由 DSA/ECDSA 签名者生成的签名并返回一个元组 (r,s)。这些签名是 ASN.1 编码的 Dss-Sig-Value 序列(如 RFC 3279 中所定义)

虽然理论上

Ed25519 是一种使用 EdDSA 和 Curve25519 的椭圆曲线签名算法。如果您没有遗留互操作性问题,那么您应该强烈考虑使用此签名算法。

就本程序而言,sign产生的值不符合decode_dss_signature的预期输入

在将公钥和私钥传递给 decode_dss_signature 之前,我尝试了所有可能的公钥和私钥编码。虽然更改编码和格式确实改变了收到 ValueError 的速率和类型,但我仍然始终收到相同类型的错误。

可能有一种方法可以确保生成的私钥符合 decode_dss_signature 的预期标准,但我无法找到有关此特定功能的文档或用例的太多信息。

由于 encode_dss_signaturedecode_dss_signatureED25519 的行为不符合预期,我最终直接返回了 signverify 的结果。

import json
import uuid

from cryptography.exceptions import InvalidSignature
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey


class Wallet:
    """
    An individual wallet for a miner.
    Keeps track of the miners's balance.
    Allows a miner to authorize transactions.
    """

    def __init__(self):
        self.address = str(uuid.uuid4())[0:8]
        self.private_key = Ed25519PrivateKey.generate()
        self.public_key = self.private_key.public_key()
        self.serialize_public_key()

    def sign(self,data):
        """
        Generate a signature based on the data using the local private key.
        """
        return self.private_key.sign(
            json.dumps(data).encode('utf-8')
        )

    def serialize_public_key(self):
        """
        Reset the public key to its serialized version.
        """
        self.public_key = self.public_key.public_bytes(
            encoding=serialization.Encoding.PEM,format=serialization.PublicFormat.SubjectPublicKeyInfo
        ).decode('utf-8')

    @staticmethod
    def verify(public_key,signature,data):
        """
        Verify signature based on original public_key and data.
        """

        deserialized_public_key = serialization.load_pem_public_key(
            public_key.encode('utf-8')
        )

        try:
            deserialized_public_key.verify(
                signature,json.dumps(data).encode('utf-8')
            )
            return True
        except InvalidSignature:
            return False


def main():
    wallet = Wallet()

    data = {'foo': 'bar'}

    signature = wallet.sign(data)
    print(f'signature: {signature}')

    sign_verification = Wallet.verify(wallet.public_key,data)
    print(f'sign_verification: {sign_verification}')

    sign_verify_failed = Wallet.verify(Wallet().public_key,data)
    print(f'sign_verify_failed: {sign_verify_failed}')


if __name__ == '__main__':
    main()

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...