多签钱包、MPC钱包及混合方案

多签钱包、MPC钱包及混合方案详解

一、多签钱包和MPC钱包的区别

特性 多签钱包 MPC钱包
私钥管理 每个参与者持有完整私钥分片,共m个私钥 私钥通过密码学算法拆分为n个碎片,无完整私钥存在
签名机制 需收集至少k个完整签名,在链上验证 链下聚合部分签名,生成一个有效签名提交链上
安全性 依赖参与者诚实性,单点泄露有风险 抗合谋攻击,单点泄露不影响整体安全
链上记录 所有签名公开可见,透明度高 仅显示最终签名,隐私性好
效率 多次链上交互,Gas费高 一次链上提交,效率高
兼容性 依赖链上多签脚本或合约 兼容所有支持标准签名的区块链

二、多签+MPC混合方案

混合方案结合了两者优势:使用MPC技术生成和管理私钥碎片,同时采用多签机制控制签名阈值,实现"分布式密钥生成+多方授权验证"的双重安全。

核心设计思路

  1. 采用MPC技术生成私钥碎片,避免完整私钥存在
  2. 设置多签阈值控制(如3-of-5),需足够多参与方共同签名
  3. 链下聚合签名,链上验证签名有效性和阈值达标情况

以下是“多签+MPC混合方案”的具体实现代码,包含链下MPC签名模块链上多签验证合约,核心逻辑是:通过MPC生成分布式签名,再通过多签合约验证签名是否符合阈值要求。

1、链下MPC签名模块(Python实现门限签名)

基于Shamir秘密共享和ECDSA门限签名,实现私钥分片生成与签名聚合(模拟MPC核心逻辑)。

import random
import hashlib
from typing import List, Tuple
from ecdsa import SigningKey, VerifyingKey, NIST256p
from ecdsa.util import number_to_string, string_to_number

# 椭圆曲线参数(兼容以太坊secp256k1,此处简化用NIST256p)
curve = NIST256p
generator = curve.generator
order = curve.order

class MPCThresholdSign:
    def __init__(self, threshold: int, num_parties: int):
        self.threshold = threshold  # 签名阈值(如3-of-5)
        self.num_parties = num_parties  # 参与方数量
        self.private_shares = []  # 私钥分片
        self.public_keys = []  # 各参与方的公钥(用于验证部分签名)

    def generate_keys(self) -> None:
        """生成MPC私钥分片和对应公钥"""
        # 生成随机多项式(k-1次)
        coefficients = [random.randint(1, order-1) for _ in range(self.threshold)]
        # 私钥分片 = 多项式在x=1..n处的取值
        for x in range(1, self.num_parties+1):
            share = 0
            for i in range(self.threshold):
                share += coefficients[i] * (x ** i)
                share %= order
            self.private_shares.append(share)
        # 计算对应公钥(用于验证部分签名)
        for share in self.private_shares:
            pub_key = (share * generator).to_string()
            self.public_keys.append(pub_key)

    def partial_sign(self, share_idx: int, message: bytes) -> Tuple[int, int]:
        """生成部分签名(每个参与方用自己的分片签名)"""
        if share_idx < 0 or share_idx >= self.num_parties:
            raise ValueError("无效的参与方索引")
        sk = self.private_shares[share_idx]
        # 计算消息哈希
        hash_msg = hashlib.sha256(message).digest()
        hash_int = int.from_bytes(hash_msg, byteorder='big') % order
        # ECDSA部分签名(简化版)
        k = random.randint(1, order-1)  # 随机数
        r = (k * generator).x() % order  # 签名r值
        s = (pow(k, -1, order) * (hash_int + sk * r)) % order  # 部分签名s值
        return (r, s)

    def aggregate_signatures(self, partial_sigs: List[Tuple[int, int]]) -> Tuple[int, int]:
        """聚合部分签名为完整ECDSA签名(需满足阈值)"""
        if len(partial_sigs) < self.threshold:
            raise ValueError(f"需要至少{self.threshold}个部分签名")
        # 拉格朗日插值聚合s值(简化逻辑)
        r = partial_sigs[0][0]  # 假设所有r值相同(实际需验证)
        s_total = 0
        for i in range(len(partial_sigs)):
            x_i = i + 1  # 参与方索引(1-based)
            # 拉格朗日系数
            lagrange = 1
            for j in range(len(partial_sigs)):
                if i != j:
                    x_j = j + 1
                    lagrange *= (0 - x_j) * pow(x_i - x_j, -1, order)
                    lagrange %= order
            s_total += partial_sigs[i][1] * lagrange
            s_total %= order
        return (r, s_total)

2、链上多签验证合约(Solidity实现)

合约负责验证MPC生成的签名是否符合多签阈值,并执行交易。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";

/**
 * @title MultiSigMPC
 * @dev 多签+MPC混合方案:链上验证MPC生成的签名是否符合多签阈值
 */
contract MultiSigMPC is ReentrancyGuard {
    using ECDSA for bytes32;

    address[] public signers;  // MPC参与方地址(公钥哈希)
    uint256 public threshold;  // 签名阈值(如3-of-5)
    mapping(bytes32 => uint256) public signatureCount;  // 交易哈希→已签名次数

    event TransactionProposed(bytes32 indexed txHash, address proposer, address to, uint256 value, bytes data);
    event TransactionSigned(bytes32 indexed txHash, address signer, uint256 count);
    event TransactionExecuted(bytes32 indexed txHash, address executor);

    /**
     * @param _signers MPC参与方地址列表
     * @param _threshold 签名阈值(需≤参与方数量)
     */
    constructor(address[] memory _signers, uint256 _threshold) {
        require(_signers.length > 0, "至少需要1个参与方");
        require(_threshold > 0 && _threshold <= _signers.length, "无效阈值");
        signers = _signers;
        threshold = _threshold;
    }

    /**
     * @dev 检查地址是否为MPC参与方
     */
    function isSigner(address _addr) public view returns (bool) {
        for (uint256 i = 0; i < signers.length; i++) {
            if (signers[i] == _addr) return true;
        }
        return false;
    }

    /**
     * @dev 提交MPC生成的签名,累计签名次数
     * @param to 接收地址
     * @param value 转账金额
     * @param data 附加数据
     * @param r ECDSA签名r值
     * @param s ECDSA签名s值
     */
    function signTransaction(
        address to,
        uint256 value,
        bytes calldata data,
        uint256 r,
        uint256 s
    ) external nonReentrant {
        require(isSigner(msg.sender), "不是授权参与方");
        // 计算交易哈希(用于去重和计数)
        bytes32 txHash = keccak256(abi.encodePacked(to, value, data, block.chainid));
        // 验证签名是否由msg.sender的MPC分片生成(核心:关联MPC公钥与地址)
        bytes32 messageHash = txHash.toEthSignedMessageHash();
        address signer = messageHash.recover(uint256(r), uint256(s));
        require(signer == msg.sender, "签名无效(与参与方地址不匹配)");

        // 累计签名次数
        signatureCount[txHash]++;
        emit TransactionSigned(txHash, msg.sender, signatureCount[txHash]);
    }

    /**
     * @dev 当签名次数达标时,执行交易
     */
    function executeTransaction(
        address to,
        uint256 value,
        bytes calldata data,
        uint256 r,
        uint256 s
    ) external nonReentrant returns (bool) {
        bytes32 txHash = keccak256(abi.encodePacked(to, value, data, block.chainid));
        require(signatureCount[txHash] >= threshold, "签名次数未达标");

        // 再次验证聚合签名有效性(最终确认)
        bytes32 messageHash = txHash.toEthSignedMessageHash();
        address aggSigner = messageHash.recover(uint256(r), uint256(s));
        // 聚合签名需对应MPC公钥(此处简化为检查是否为参与方之一)
        require(isSigner(aggSigner), "聚合签名无效");

        // 执行交易
        (bool success, ) = to.call{value: value}(data);
        require(success, "交易执行失败");
        emit TransactionExecuted(txHash, msg.sender);
        return success;
    }

    // 接收ETH
    receive() external payable {}
}

3、混合方案工作流程(使用示例)

# 1. 初始化MPC门限签名(3-of-5方案)
mpc = MPCThresholdSign(threshold=3, num_parties=5)
mpc.generate_keys()
print("MPC参与方公钥:", [pk.hex()[:10]+"..." for pk in mpc.public_keys])

# 2. 生成交易数据
message = b"transfer 1 ETH to 0x742d35Cc6634C0532925a3b844Bc454e4438f44e"

# 3. MPC参与方生成部分签名(模拟3个参与方签名)
partial_sigs = []
for i in [0, 2, 4]:  # 选择3个参与方
    sig = mpc.partial_sign(share_idx=i, message=message)
    partial_sigs.append(sig)
    print(f"参与方{i}的部分签名: (r={sig[0]}, s={sig[1]})")

# 4. 聚合部分签名为完整签名
agg_sig = mpc.aggregate_signatures(partial_sigs)
print("聚合后的完整签名: (r={}, s={})".format(agg_sig[0], agg_sig[1]))

# 5. 链上多签合约验证与执行(模拟)
"""
Solidity合约部署后,执行流程:
1. 3个MPC参与方分别调用signTransaction,提交签名
2. 当签名计数≥3时,调用executeTransaction执行转账
3. 合约验证签名有效性和参与方权限,最终完成交易
"""

4、核心逻辑说明

  1. 链下MPC模块

    • 通过Shamir秘密共享生成5个私钥分片,每个参与方持有1个。
    • 交易签名时,至少3个参与方生成部分签名,通过拉格朗日插值聚合为完整ECDSA签名(符合区块链标准)。
  2. 链上多签合约

    • 维护授权参与方列表和签名阈值(3-of-5)。
    • 参与方提交签名后,合约累计计数,达到阈值后允许执行交易。
    • 关键验证:确保签名来自授权参与方,防止未授权签名。
  3. 混合优势

    • MPC确保私钥不落地(无单点泄露风险),多签合约确保签名符合阈值(防少数人滥用)。
    • 签名在链下聚合(高效),验证在链上完成(透明可审计)。

该方案兼顾了MPC的分布式安全和多签的链上可控性,适合机构级资产托管(如交易所冷钱包、DAO国库)等高频次、高安全性需求场景。实际生产环境中需补充密码学安全细节(如防重放攻击、随机数安全生成)和合约审计。

三、混合方案工作流程解析

graph TD %% 初始化阶段 A["开始"] --> B["创建混合方案配置(设置3-of-5门限)"] B --> C["MPC分布式密钥生成\n• 生成随机多项式\n• 拆分私钥为5个碎片"] C --> D["分发生成:\n• 5个私钥碎片(分发给参与方)\n• 群组公钥(链上可见)\n• 分片公钥(验证用)"] %% 签名生成阶段 D --> E["发起交易(含转账信息、接收地址)"] E --> F["参与方生成部分签名\n• 基于各自私钥碎片\n• 输出部分签名(r_i,s_i)"] %% 签名聚合阶段 F --> G{"收集到≥3个部分签名?"} G -->|否| H["等待更多签名"] G -->|是| I["MPC签名聚合\n• 拉格朗日插值法\n• 聚合为完整签名(R,S)"] %% 多签验证阶段 I --> J["多签合约验证\n1. 检查签名计数≥3\n2. 验证聚合签名与群组公钥匹配"] J --> K{"验证通过?"} K -->|否| L["交易驳回"] K -->|是| M["执行交易(资产转移完成)"]
  1. 初始化阶段

    • 创建门限签名器,设置参数(如3-of-5,表示5个参与方中至少需要3个签名)
    • 生成私钥分片:使用Shamir秘密共享算法,将私钥拆分为5个分片,每个参与方持有一个
    • 计算公钥:每个分片对应一个公钥,同时生成群组公钥(等同于完整私钥对应的公钥)
  2. 签名阶段

    • 交易发起后,参与方使用自己的私钥分片生成部分签名
    • 部分签名包含r和s值,仅使用分片信息,不涉及完整私钥
  3. 聚合阶段

    • 收集至少3个部分签名
    • 使用拉格朗日插值算法聚合部分签名,生成完整有效的签名
    • 聚合过程不需要恢复完整私钥,直接通过数学运算组合
  4. 验证阶段

    • 多签验证器检查签名数量是否达到阈值
    • 验证聚合签名是否有效(使用群组公钥)
    • 验证通过后执行交易

四、混合方案的优势与应用场景

优势

  1. 安全性增强:MPC防止完整私钥泄露,多签机制防止单点滥用
  2. 灵活性高:可动态调整参与方和阈值,适应不同场景需求
  3. 兼容性好:生成的签名与标准签名格式兼容,可在任何支持ECDSA的区块链上使用
  4. 可审计性:多签机制保留签名记录,满足合规审计需求

应用场景

  1. 机构资产托管:交易所冷钱包、银行数字资产储备
  2. DAO国库管理:集体决策管理组织资金
  3. 跨境支付:多方授权的大额跨境转账
  4. 高安全要求场景:医疗数据加密、政务系统密钥管理

混合方案结合了MPC的分布式密钥安全和多签的权限控制优势,是目前高价值数字资产管理的最佳实践之一。

posted @ 2025-07-23 17:57  ffffox  阅读(115)  评论(0)    收藏  举报