从 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 方案放在最后,因为它通常不在通用库中;我认为这是专家出路。您可能会遇到学习曲线。
顺便说一下,签名本身压缩得不好,除非你对它们进行糟糕的编码。压缩的另一个缺点是计算所有可能消息的最大大小通常很棘手。
我正在使用 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 方案放在最后,因为它通常不在通用库中;我认为这是专家出路。您可能会遇到学习曲线。
顺便说一下,签名本身压缩得不好,除非你对它们进行糟糕的编码。压缩的另一个缺点是计算所有可能消息的最大大小通常很棘手。