BSV 上的私钥谜题

我们引入了一种称为私钥谜题的新型 BSV 智能合约,它只能通过提供给定公钥的对应私钥来解锁。

在以前的合约中,只需要以数字签名的形式证明拥有私钥。私钥保密,不会暴露。私钥谜题合约则相反,私钥是被公开的。

对 ECDSA 的 Nonce 重用攻击

为了生成签名,ECDSA 需要一个私钥 d、一个随机数 k(称为 nonce)和消息的散列 hr 是点 k * Gx 坐标,其中 G 是生成器。

在这里插入图片描述

(r, s) 就是签名。

当使用相同的私钥和相同随机数 k 的对不同消息进行签名时,就会出现问题。我们将有两个签名 (r, s1) 和 (r, s2)。 r 相同,因为 k 相同。
在这里插入图片描述

在这里插入图片描述

我们可以通过以下方式恢复随机数:

在这里插入图片描述

我们还可以通过以下方式恢复私钥:

在这里插入图片描述

索尼 PlayStation 3 因为暴露了此漏洞被黑客入侵。因此,为不同的签名选择不同的 k 至关重要。

私钥谜题

我们将利用漏洞来间接曝光私钥。我们有意要求对使用相同私钥和随机数签名的两条不同消息的两个有效签名,如下所示。

contract PrivateKeyPuzzle {
    PubKey pubKey;

    // extract r from DER-encoded signature
    static function extractRFromSig(Sig sig) : bytes {
        int rlen = unpack(sig[3 : 4]);
        return sig[4 : 4 + rlen];
    }

    public function unlock(Sig sig1, Sig sig2) {
        require(checkSig(sig1, this.pubKey));
        // ensure signed messages are different option (1): insert CODESEPERATOR in between two checkSigs
        ***
        require(checkSig(sig2, this.pubKey));

        // sign with same r, thus same ephemeral key k
        require(extractRFromSig(sig1) == extractRFromSig(sig2));
    }
}
PrivateKeyPuzzle 合约

我们在第 11 行和第 14 行验证两个签名使用了相同的公钥和私钥。 第 5 行的函数 extraRFromSig() 允许我们从签名中提取 r,DER 编码如下。

在这里插入图片描述

17 行确保 r 相同,因此在两个签名中相同的 k 使用。

签名的消息称为 sighash 原像。请注意,我们在第 13 行插入了一个 OP_CODESEPARATOR 以确保两个签名的消息是不同的,因为它们具有不同的 scriptCode(sighash 原像的第 5 部分)。

还有其他方法可以确保签名消息不同。例如,我们可以在签名时使用不同的 sighash 标志(sighash 原像的第 10 部分)。


// extract SIGHASH flag from DER-encoded signature
static function extractSighashFlagFromSig(Sig sig) : SigHashType {
    int len = len(sig);
    return SigHashType(sig[len - 2 : ]);
}

public function unlock(Sig sig1, Sig sig2) {
    require(checkSig(sig1, this.pubKey));
    require(checkSig(sig2, this.pubKey));

    // ensure signed messages are different option (2): use different sighash flags
    require(extractSighashFlagFromSig(sig1) == (SigHash.NONE | SigHash.FORKID));
    require(extractSighashFlagFromSig(sig2) != (SigHash.NONE | SigHash.FORKID));

    // sign with same r, thus same ephemeral key k
    require(extractRFromSig(sig1) == extractRFromSig(sig2));
}
PrivateKeyPuzzle 合约

sig1 使用 NONE ,将交易输出的从签名的消息中排除,而 sig2 包含了交易输出,因此不同。

替代实现

还有其他方法可以强制公开私钥:

私钥谜题比它们更紧凑和高效。

致谢

本文改编自论文比特币私钥锁定交易的想法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sCrypt Web3应用开发

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值