由ECDSA签名延展性产生的重放

○ 介绍



签名延展性指的是:网络中的任何中继节点,不需要获取对应交易的私钥, 而修改该交易签名的能力。而ECDSA自身的签名延展性是指其自身具有延展性,因为内部S的负值不会使签名无效。这意味着如果在签名中没有加入限制条件,攻击者可以为相同的数据创建第二有效的签名,从而发生“双花”。



● 原理



ECDSA 签名由r与s两部分组成,两者都是256-bit数字,在ssecp256k1(y2 = x3 + 7(mod p))曲线上(其中 p 是一个非常大的素数),两者都是256-bit数字。这通常表示为元组 [r, s]。

在签署交易时,我们会创建一个随机的临时私钥以包含在签名中。然后,使用这个临时私钥点在 Secp256k1 椭圆曲线上生成一个对应的点 P,将该公钥点的 X 坐标用作我们的 r 值,而s = (z+re)/k。但椭圆曲线上实际上有两个点具有此 X 值:P1 和 P2。

由ECDSA签名延展性产生的重放



○ 实例



本实例来自Mr Steal Yo Crypto CTF

链接

https://mrstealyocrypto.xyz/malleable/index.html
// SPDX-License-Identifier: MITpragma solidity ^0.8.0;
contract TreasureVault {
bytes32 public immutable DOMAIN_SEPARATOR; bytes32 public constant TYPEHASH = keccak256("SendFundsWithAuth(uint256 amount,uint256 nonce)");
mapping(bytes32 => bool) usedHash;
address public immutable owner;
constructor() { owner = msg.sender;
DOMAIN_SEPARATOR = keccak256( abi.encode( keccak256( "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" ), keccak256(bytes("TreasureVault")), keccak256(bytes("1")), getChainid(), address(this) ) ); }
receive() external payable {}
function sendFundsWithAuth( uint256 amount, uint256 nonce, uint8 v, bytes32 r, bytes32 s) external { require(tx.origin == msg.sender,'EOA');
bytes32 structHash = keccak256(abi.encode(TYPEHASH, amount, nonce)); bytes32 digest = keccak256(abi.encodePacked("x19x01", DOMAIN_SEPARATOR, structHash)); address signatory = ecrecover(digest, v, r, s); require(signatory == owner,'invalid sig');
bytes32 signatureHash = keccak256(abi.encodePacked(v, r, s)); require(!usedHash[signatureHash],'sig reuse'); usedHash[signatureHash]=true;
(bool success,) = payable(msg.sender).call{value:amount}(''); require(success); }
function removeFunds() external { require(msg.sender == owner,'invalid caller');
(bool success,) = payable(msg.sender).call{value:address(this).balance}(''); require(success); }
function getChainid() public view returns (uint256) { return block.chainid; }
}

在此合约中,调用方可以指定其签名的 v、r 和 s 值,以验证自己是所有者并转移资金。但是由于ECDSA 签名的内在延展性,因此攻击者可以修改s = bytes32

(     uint256(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141) – uint256(s) );

并使用对应的v,从而将相同的金额转移给自己。



● 引用说明



引用链接:

https://www.derpturkey.com/inherent-malleability-of-ecdsa-signatures/


作者:于文杰

编辑:舒婷


原文始发于微信公众号(ChainSecLabs):由ECDSA签名延展性产生的重放

版权声明:admin 发表于 2024年2月27日 下午9:32。
转载请注明:由ECDSA签名延展性产生的重放 | CTF导航

相关文章