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

时间:2018-03-22 20:09:25

标签: java cryptography digital-signature bouncycastle ecdsa

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

2 个答案:

答案 0 :(得分:2)

ECDSA要求对邮件的哈希是安全的。所以所有信息都丢失了。一些签名方案使用消息的散列+部分。例如,ISO / IEC 9796签名方案中的RSA给出(部分)消息恢复 - 这是您(和Dave Thompson)所谈论的技术术语。

然而,ECDSA签名足以包含单个哈希(通常甚至不包含);没有太多可以做的事情来将数据添加到哈希值。尝试使用EC签名进行部分邮件恢复是徒劳的(也是因为如何执行验证)。

但是如果你想使用更少的比特,你仍然可以做的事情:

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

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

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

答案 1 :(得分:1)

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

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

 AttachedSignature = zip(format(message + signature))