从 ECDSA 签名中放置和提取文本

Put and extract text from ECDSA Signature

我正在使用 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 )
        {
        }
    }
}

数字签名、ECDSA 或 RSA 通常不包含消息(请参阅@dave_thompson_085 评论)。 "attached signature"指的是一个文件,基本上包含消息和数字签名,可以用CMS或XMLDsig格式编码。

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

 AttachedSignature = zip(format(message + signature))

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

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


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

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

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


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