资讯专栏INFORMATION COLUMN

区块链中的DCDSA:椭圆曲线数字签名

dack / 1679人阅读

摘要:既然我们已经可以产生椭圆曲线密钥对,我们接下来就用使用它来进行消息的签名和验证。签名椭圆曲线签名算法就是在中,各方必须约定一个共同的哈希函数因为我们将要签名的对象是消息,而不是消息本身。这种行为也是造成交易可塑性的原因之一。

既然我们已经可以产生椭圆曲线密钥对,我们接下来就用使用它来进行消息的签名和验证。我所指的消息是任何形式,无论是文本还是二进制形式,只要它们有被验证合法性的需要。特别的是,bitcoin客户端通过签名来证明交易的有效性,反之,矿工则是通过验证这样的签名,来批准并广播合法的交易。

ECDSA 签名

椭圆曲线签名算法就是ECDSA(Elliptic-Curve Digital Signature Algorithm).在ECDSA中,各方必须约定一个共同的哈希函数H, 因为我们将要签名的对象是H(消息),而不是消息本身。值得注意的是,只有签名方S有私钥的权限,验证方V只需要拿到相应的公钥就可以进行验证。本文中,我将使用上一章所创建的密钥对。

下面的案例中,我们签名的对象是SHA-256摘要。但bitcoin中指定的H函数是HASH256,也就是指双重SHA-256

签名

第一步把我们的消息存入文件,命名ex-message.txt

This is a very confidential message

之后,我们用私钥对其SHA-256摘要进行签名。

$ openssl dgst -sha256 -sign ec-priv.pem ex-message.txt >ex-signature.der

ex-signature.der文件是签名的DER格式。OpenSSL使用DER编码任何二进制输出,但这里我们忽略这个细节。你不需要了解ECDSA签名的语法,只需要记住它仅仅是一组的大数对(r,s)

你可能会注意到,每一次你执行程序,签名都发生变化,也就是说默认的签名过程是不具有确定性的。这就给序列化区块链交易时带来了问题,因为签名是交易字节序列中的一部分,并且你一定知道txid是对交易进行哈希得来的。因此,每当你签名一笔交易txid就会随之变化。这种行为也是造成交易可塑性的原因之一。

为了显示十六进制编码的签名,只需添加-hex参数。

$ openssl dgst -sha256 -hex -sign ec-priv.pem ex-message.txt

为了重用刚刚输出的结果,最好使用hexdup已生成的DER文件。

$ hexdump ex-signature.der
验证

无论什么时候将合法消息发布到网络,接收者都希望能够得到一个附件的签名。在假设我们已经得到作者公钥的情况下,无论是原消息还是签名,都必须作为验证流程的输入数据:

$ openssl dgst -sha256 -verify ec-pub.pem -signature ex-signature.der ex-message.txt
代码版本

我们使用代码来完成上文中在命令行中完成的同样的工作。

签名

OpenSSL使签名流程变得简单,这一部分可以在 ex-ecdsa-sign.c中查看。

uint8_t priv_bytes[32] = { ... };
const char message[] = "This is a very confidential message
";

EC_KEY *key;
uint8_t digest[32];
ECDSA_SIG *signature;
uint8_t *der, *der_copy;
size_t der_len;

...

key = bbp_ec_new_keypair(priv_bytes);
bbp_sha256(digest, (uint8_t *)message, strlen(message));
signature = ECDSA_do_sign(digest, sizeof(digest), key);

ECDSA_SIG是一个简单的结构,用于存储上文所说的(r,s)对:

struct {
    BIGNUM *r;
    BIGNUM *s;
} ECDSA_SIG;

使用i2d_ECDSA_SIG函数,我们也可以得到DER编码的签名:

der_len = ECDSA_size(key);
der = calloc(der_len, sizeof(uint8_t));
der_copy = der;
i2d_ECDSA_SIG(signature, &der_copy);
验证

验证同样很简单,可以在ex-ecdsa-verify.c中查看:

uint8_t pub_bytes[33] = { ... };
uint8_t der_bytes[] = { ... };
const char message[] = "This is a very confidential message
";

EC_KEY *key;
const uint8_t *der_bytes_copy;
ECDSA_SIG *signature;
uint8_t digest[32];
int verified;

...

key = bbp_ec_new_pubkey(pub_bytes);
der_bytes_copy = der_bytes;
signature = d2i_ECDSA_SIG(NULL, &der_bytes_copy, sizeof(der_bytes));

因为无法得到私钥,我们利用使用下面的辅助函数将pub_bytes解码为压缩形式。

EC_KEY *bbp_ec_new_pubkey(const uint8_t *pub_bytes, size_t pub_len);

另一方面,der_bytes是签名程序返回的DER格式的签名。我们将解码DER签名到更方便的ECDSA_SIG结构中,然后与消息摘要比较进行验证。

ECDSA_do_verify函数的返回值:

1,签名合法

0,签名不合法

-1,出现未知错误

注意:使用ECDSA_verify可以跳过签名的解码过程,因为它需要的输入值是DER形式的签名。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/23965.html

相关文章

  • 区块链中密钥对的生成原理

    摘要:通过命令行中显示结论压缩形式占据一个或的前缀的坐标从代码中生成注原文作者的密钥对的产生过程是冗长的,然而使用来完成却不难。可以是一个完整的密钥对或者是一个单独的公钥。 bitcoin中的密钥综述 关于bitcon中使用的椭圆曲线加密体制的一些事实: 私钥长度 32bytes 公钥长度 64bytes (未压缩形式) 或者 32bytes(压缩形式)+ 1byte(前缀) 椭圆曲线...

    jackzou 评论0 收藏0
  • 是的我想说的技术!

    摘要:有效的数字签名使收件人有理由相信该信息是由已知的发件人认证创建的,发件人不能否认已发送的信息不可否认,并且信息在传输过程中未被更改完整性。当我们说签署交易时,我们实际上是指签署序列化交易数据的哈希。 特殊交易:合约注册 有一种特殊的带有data,没有value的交易。表示注册一个新的合约。合约登记交易被发送到一个特殊的目的地地址,即零地址。简而言之,合约注册交易中的+to+字段包含地址...

    focusj 评论0 收藏0
  • 区块链之公钥、私钥、地址之间的关系

    摘要:公钥哈希和钱包地址可以通过互逆运算进行转换,所以它们是等价的。使用私钥对交易进行签名比特币钱包间的转账是通过交易实现的。使用公钥对签名进行验证交易数据被广播到比特币网络后,节点会对这个交易数据进行检验,其中就包括对签名的校验。 一句话解释公钥、私钥、地址私钥:实际上是一组随机数,关于区块链中的随机数我们已经介绍过了公钥:对私钥进行椭圆曲线加密算法生成,但是无法通过公钥倒推得到私钥。公...

    104828720 评论0 收藏0
  • 基于Java语言构建区块链(五)—— 地址(钱包)

    摘要:本质上,比特币钱包就是一对这样的密钥。例如,一个错误比特币地址就不会被钱包认为是有效的地址,否则这种错误会造成资金的丢失。 showImg(https://segmentfault.com/img/remote/1460000013982997?w=1920&h=1053); 最终内容请以原文为准:https://wangwei.one/posts/f90... 引言 在 上一篇 文...

    entner 评论0 收藏0
  • 区块链的基石--椭圆曲线密码学

    摘要:如果公式解析有问题,请移步备份链接椭圆曲线密码学椭圆曲线密码学是基于椭圆曲线数学的一种公钥加密方法。椭圆曲线数字签名什么是数字签名现实生活中的签名作用是签署者对文件进行授权防止交易中的抵赖发生。 如果SF公式解析有问题,请移步备份链接 https://blog.csdn.net/chenmo1... 椭圆曲线密码学 椭圆曲线密码学(ECC, Elliptic Curve Crypt...

    DoINsiSt 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<