PHP项目中的门限签名与BLS方案
基本概念
门限签名(Threshold Signature):

- 需要 t-of-n 个签名者协作生成有效签名
- 任意 t 个参与者可签名,少于 t 个无法签名
- 最终签名的验证方式与单签名相同
BLS(Boneh-Lynn-Shacham)签名:
- 基于双线性配对(Bilinear Pairing)
- 支持签名聚合
- 天然适合门限签名实现
PHP实现方案
使用现有库(推荐)
// 使用 bls-signatures 库(需要安装C扩展或使用纯PHP实现) composer require phosphor/bls-signatures // 基本使用示例 use Phosphor\BLS\PrivateKey; use Phosphor\BLS\PublicKey; use Phosphor\BLS\Signature; // 生成密钥对 $privateKey = new PrivateKey(); $publicKey = $privateKey->toPublicKey(); // 签名 $message = "Hello World"; $signature = $privateKey->sign($message); // 验证 $result = $publicKey->verify($signature, $message); // 聚合签名 $aggregatedSig = Signature::aggregate([$sig1, $sig2, $sig3]);
使用Libsodium + 自定义门限方案
class ThresholdBLS {
private $threshold;
private $total;
private $privateKeyShares;
private $publicKeyShares;
public function __construct($threshold, $total) {
$this->threshold = $threshold;
$this->total = $total;
}
// 生成Shamir秘密共享参数
public function generateShares($masterPrivateKey) {
// 使用多项式插值法
$coefficients = $this->generateRandomCoefficients($this->threshold - 1);
$coefficients[0] = $masterPrivateKey;
$shares = [];
for ($i = 1; $i <= $this->total; $i++) {
$share = 0;
foreach ($coefficients as $j => $coeff) {
$share += $coeff * pow($i, $j);
}
$shares[$i] = $share;
}
return $shares;
}
// 部分签名
public function partialSign($message, $privateKeyShare) {
// 使用BLS签名算法
return hash('sha256', $message . $privateKeyShare);
}
// 聚合部分签名
public function aggregateSignatures($partialSignatures, $indices) {
// Lagrange插值聚合
$aggregatedSig = 0;
foreach ($partialSignatures as $i => $sig) {
$lambda = $this->lagrangeCoefficient($i, $indices);
$aggregatedSig += $lambda * $sig;
}
return $aggregatedSig;
}
}
使用成熟的密码学库
使用 BN曲线库(支持BLS)
// 安装 bncurve-php
composer require simplito/bncurve-php
class BLSSignature {
private $curve;
public function __construct() {
$this->curve = new \SIMPLITO\BNCurve();
}
public function generateKeyPair() {
$privateKey = $this->curve->randomScalar();
$publicKey = $this->curve->multiplyBasePoint($privateKey);
return [
'private' => $privateKey,
'public' => $publicKey
];
}
public function sign($message, $privateKey) {
$hash = $this->hashToCurve($message);
return $this->curve->multiplyPoint($hash, $privateKey);
}
public function verify($message, $signature, $publicKey) {
$hash = $this->hashToCurve($message);
// e(signature, G2) == e(hash, publicKey)
$pairing1 = $this->curve->pairing($signature, $this->curve->generatorG2());
$pairing2 = $this->curve->pairing($hash, $publicKey);
return $pairing1->equals($pairing2);
}
private function hashToCurve($message) {
// 实现哈希到曲线的映射
$hash = hash('sha256', $message, true);
$x = gmp_import($hash);
return $this->curve->pointFromX($x);
}
}
完整门限签名实现示例
<?php
class ThresholdBLSSystem {
private $participantKeys = [];
private $threshold;
private $totalParticipants;
private $curve;
public function __construct($threshold, $total) {
$this->threshold = $threshold;
$this->totalParticipants = $total;
$this->curve = new \SIMPLITO\BNCurve();
}
// 分布式密钥生成 (DKG)
public function distributedKeyGeneration() {
// 每个参与者生成自己的秘密
$masterSecret = $this->curve->randomScalar();
// 生成Shamir分享
$shares = $this->generateShamirShares($masterSecret);
// 分发份额到各节点
for ($i = 0; $i < $this->totalParticipants; $i++) {
$this->participantKeys[$i] = [
'share' => $shares[$i],
'index' => $i + 1
];
}
// 计算公钥
$masterPublicKey = $this->curve->multiplyBasePoint($masterSecret);
return [
'master_public_key' => $masterPublicKey,
'participants' => $this->participantKeys
];
}
// 门限签名
public function thresholdSign($message, $signingParticipants) {
if (count($signingParticipants) < $this->threshold) {
throw new Exception("需要至少 {$this->threshold} 个参与者");
}
$partialSignatures = [];
$indices = [];
// 每个参与者生成部分签名
foreach ($signingParticipants as $participantId) {
$key = $this->participantKeys[$participantId];
$partialSig = $this->partialSign($message, $key['share']);
$partialSignatures[] = $partialSig;
$indices[] = $key['index'];
}
// 聚合部分签名
return $this->aggregateSignatures($partialSignatures, $indices);
}
// 部分签名计算
private function partialSign($message, $privateShare) {
$hash = hash('sha256', $message, true);
$hashPoint = $this->curve->pointFromX(gmp_import($hash));
return $this->curve->multiplyPoint($hashPoint, $privateShare);
}
// Lagrange插值聚合
private function aggregateSignatures($signatures, $indices) {
$aggregated = null;
foreach ($signatures as $i => $sig) {
$lambda = $this->lagrangeCoefficient($indices[$i], $indices);
$weighted = $this->curve->multiplyPoint($sig, $lambda);
if ($aggregated === null) {
$aggregated = $weighted;
} else {
$aggregated = $this->curve->addPoints($aggregated, $weighted);
}
}
return $aggregated;
}
// Lagrange系数计算
private function lagrangeCoefficient($index, $indices) {
$result = gmp_init(1);
foreach ($indices as $j) {
if ($j !== $index) {
// λ_i = Π (x - x_j) / (x_i - x_j)
$numerator = gmp_sub(gmp_init(0), gmp_init($j)); // 0 - j
$denominator = gmp_sub(gmp_init($index), gmp_init($j)); // i - j
// 求模逆元
$modInverse = $this->modInverse($denominator);
$result = gmp_mul($result, gmp_mul($numerator, $modInverse));
}
}
return $result;
}
// Shamir秘密共享
private function generateShamirShares($secret) {
$coefficients = [$secret];
// 生成随机系数
for ($i = 1; $i < $this->threshold; $i++) {
$coefficients[] = $this->curve->randomScalar();
}
$shares = [];
for ($i = 1; $i <= $this->totalParticipants; $i++) {
$share = gmp_init(0);
foreach ($coefficients as $j => $coeff) {
$term = gmp_mul($coeff, gmp_pow(gmp_init($i), $j));
$share = gmp_add($share, $term);
}
$shares[] = $share;
}
return $shares;
}
}
使用注意事项
性能优化
// 缓存配对计算结果
class PairingCache {
private static $cache = [];
public static function compute($p, $q) {
$key = spl_object_hash($p) . '|' . spl_object_hash($q);
if (!isset(self::$cache[$key])) {
self::$cache[$key] = pairing($p, $q);
}
return self::$cache[$key];
}
}
安全问题
// 添加随机数确保安全性
class SecureBLS {
public function secureSign($message, $privateKey) {
$nonce = random_bytes(32);
$signedMessage = $message . $nonce;
return [
'signature' => $this->sign($signedMessage, $privateKey),
'nonce' => bin2hex($nonce)
];
}
}
推荐方案总结
生产环境推荐:
- 使用专业的密码学库:herumi/bls(通过FFI调用)
- 使用现成的区块链SDK:Ethereum BLS实现
- 考虑使用微服务架构:将密码学操作封装为独立服务
不适合纯PHP实现:
- BLS涉及复杂的椭圆曲线运算
- PHP在性能上不如C/C++/Go
- 建议使用C扩展或调用外部进程
替代方案:
- 使用Go/Rust/Python实现签名服务
- PHP通过RPC调用
- 使用成熟的DKG库(如tss-lib的绑定)
请根据具体项目需求选择合适的实现方式,生产环境建议使用经过审计的密码学库。