1

我正在尝试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, signature, data)
    print(f'sign_verification: {sign_verification}')

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

if __name__ == '__main__':
    main()
4

1 回答 1

0

我在测试中发现,根据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_signatureanddecode_dss_signature的行为与预期不符ED25519,我最终直接从signand返回了结果verify

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, signature, data)
    print(f'sign_verification: {sign_verification}')

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


if __name__ == '__main__':
    main()
于 2021-04-04T06:46:44.543 回答