【问题标题】:Put and extract text from ECDSA Signature从 ECDSA 签名中放置和提取文本
【发布时间】:2018-03-22 20:09:24
【问题描述】:

我正在使用 secp256k1 对服务器中的文本进行哈希签名并验证客户端的签名。 现在,我还需要向客户端发送实际文本,但我的主要限制是带宽,我不能单独添加文本。因此,我需要能够将实际文本放入签名中并在验证期间提取它吗?

这是我的代码

签名

 static final X9ECParameters curve = SECNamedCurves.getByName ("secp256k1");
static final ECDomainParameters domain = new ECDomainParameters(curve.getCurve (), curve.getG (), curve.getN (), curve.getH ());

public byte[] sign (byte[] hash) throws CryptoException
{
    if ( priv == null )
    {
        throw new CryptoException (ErrorCode.KEY_NOT_FOUND, "Need private key to sign");
    }
    ECDSASigner signer = new ECDSASigner(new HMacDSAKCalculator(new SHA256Digest()));
    signer.init (true, new ECPrivateKeyParameters(priv, domain));
    BigInteger[] signature = signer.generateSignature (hash);
    ByteArrayOutputStream s = new ByteArrayOutputStream();
    try
    {
        DERSequenceGenerator seq = new DERSequenceGenerator(s);
        seq.addObject (new ASN1Integer(signature[0]));
        seq.addObject (new ASN1Integer(signature[1]));
        seq.close ();
        return s.toByteArray ();
    }
    catch ( IOException e )
    {
    }
    return null;
}

验证

public static boolean verify (byte[] hash, byte[] signature, byte[] pub)
{
    ASN1InputStream asn1 = new ASN1InputStream(signature);
    try
    {
        ECDSASigner signer = new ECDSASigner();
        signer.init (false, new ECPublicKeyParameters(curve.getCurve ().decodePoint (pub), domain));

        DLSequence seq = (DLSequence) asn1.readObject ();
        BigInteger r = ((ASN1Integer) seq.getObjectAt (0)).getPositiveValue ();
        BigInteger s = ((ASN1Integer) seq.getObjectAt (1)).getPositiveValue ();
        return signer.verifySignature (hash, r, s);
    }
    catch ( Exception e )
    {
        // threat format errors as invalid signatures
        return false;
    }
    finally
    {
        try
        {
            asn1.close ();
        }
        catch ( IOException e )
        {
        }
    }
}

【问题讨论】:

    标签: java cryptography digital-signature bouncycastle ecdsa


    【解决方案1】:

    ECDSA 要求对消息进行哈希处理以确保安全。所以所有信息都丢失了。一些签名方案使用哈希+消息的一部分。例如,ISO/IEC 9796 签名方案中的 RSA 提供(部分)消息恢复 - 这是您(和 Dave Thompson)正在谈论的技术术语。

    然而,ECDSA 签名足够大,可以包含单个哈希(通常甚至不包含);您无法将数据添加到哈希值。尝试使用 EC 签名进行部分消息恢复是徒劳的(也因为如何执行验证)。


    但是,如果您想使用更少的位,您仍然可以做一些事情:

    • 使用最密集的消息和签名表示(例如,仅为 ECDSA 签名连接 R 和 S);
    • 尽可能使用最小的密钥(查看https://keylength.com/ 了解信息);
    • 切换到使用较小签名的签名方案,例如BLS signature scheme over elliptic curves - 与 ECDSA 相比,签名大小将减半(使用最有效的编码)。

    我将 BLS 方案放在最后,因为它通常不在通用库中;我认为这是专家的出路。您可能会遇到学习曲线。


    顺便说一下,签名本身不能很好地压缩,除非你对它们进行了糟糕的编码。压缩的另一个缺点是计算所有可能消息的最大大小通常很棘手。

    【讨论】:

      【解决方案2】:

      数字签名、ECDSA 或 RSA 通常不包含消息(请参阅@dave_thompson_085 评论)。 “附加签名”是指基本上包含消息和数字签名的文件,可以编码为 CMS 或 XMLDsig 格式。

      因此,如果您需要发送消息和签名,只需将它们一起发送,使用自定义或已知格式,并额外压缩以减小大小

       AttachedSignature = zip(format(message + signature))
      

      【讨论】:

      • 最常见的RSA签名方案不支持恢复but some do, within limits;对于 [EC]DSA,这是不可能的,但签名更短(通常为数据留出更多空间/带宽)。此外,CMS(+S/MIME) 和 XML 是标准化的通用格式(而不是节省空间的格式),但 PGP 也是标准的,任何数量的 ad-hoc 或自定义格式都是可能的。
      • 我想要的不仅仅是压缩在一起(这是我已经做的)或大型 PKCS#7 文件。
      • PKCS#7 文件可以包含签名和消息,其方式与我在答案中引用的格式相同。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-13
      • 2021-12-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多