密码学原语Skill crypto-primitives

本技能提供区块链和网络安全应用中核心密码学原语的实现与安全使用指南。涵盖数字签名(ECDSA、BLS、Schnorr)、密钥派生(BIP-32/39/44)、秘密共享(Shamir)、哈希函数(Keccak、Poseidon)、承诺方案(Pedersen)、安全随机数生成以及抗侧信道攻击的恒定时间操作。适用于区块链开发者、安全工程师和密码学研究人员,确保密码学实现的安全性和正确性。关键词:密码学原语、区块链安全、数字签名、密钥管理、秘密共享、零知识证明、侧信道防护、安全随机数。

加密算法 0 次安装 10 次浏览 更新于 2/23/2026

name: crypto-primitives description: 密码学原语的实现和安全使用,包括ECDSA、BLS、Schnorr签名、密钥派生、秘密共享和恒定时间操作。为区块链应用中的安全密码学实现提供指导。 allowed-tools: Read, Grep, Write, Bash, Edit, Glob, WebFetch

密码学原语技能

为区块链和安全应用提供专业的密码学原语实现和使用方法。

能力

  • 数字签名:ECDSA、BLS、Schnorr签名的实现和验证
  • 密钥派生:BIP-32/39/44分层确定性密钥生成
  • 门限密码学:Shamir秘密共享、门限签名
  • 哈希函数:Keccak、Poseidon、MiMC、Pedersen的安全使用
  • 承诺方案:Pedersen承诺、哈希承诺
  • 安全随机性:CSPRNG使用、VRF集成
  • 恒定时间操作:抗侧信道攻击的实现

签名方案

ECDSA (secp256k1)

标准的以太坊签名方案:

import { secp256k1 } from '@noble/curves/secp256k1';
import { keccak_256 } from '@noble/hashes/sha3';

// 签名消息
const messageHash = keccak_256(message);
const signature = secp256k1.sign(messageHash, privateKey);

// 验证签名
const isValid = secp256k1.verify(signature, messageHash, publicKey);

// 从签名恢复公钥(以太坊风格)
const recoveredPubKey = signature.recoverPublicKey(messageHash);

BLS 签名 (BLS12-381)

用于验证者集合的可聚合签名:

import { bls12_381 } from '@noble/curves/bls12-381';

// 使用BLS签名
const signature = bls12_381.sign(message, privateKey);

// 验证
const isValid = bls12_381.verify(signature, message, publicKey);

// 聚合签名
const aggregatedSig = bls12_381.aggregateSignatures([sig1, sig2, sig3]);
const aggregatedPubKeys = bls12_381.aggregatePublicKeys([pk1, pk2, pk3]);
const isValidAgg = bls12_381.verify(aggregatedSig, message, aggregatedPubKeys);

Schnorr 签名

符合BIP-340的Schnorr签名:

import { schnorr } from '@noble/curves/secp256k1';

// 签名(返回64字节签名)
const signature = schnorr.sign(messageHash, privateKey);

// 验证
const isValid = schnorr.verify(signature, messageHash, publicKey);

密钥派生

BIP-32 HD钱包

import { HDKey } from '@scure/bip32';
import { mnemonicToSeedSync } from '@scure/bip39';

// 从助记词生成种子
const seed = mnemonicToSeedSync(mnemonic);

// 创建HD钱包
const hdkey = HDKey.fromMasterSeed(seed);

// 派生路径(以太坊的BIP-44)
// m/44'/60'/0'/0/0
const child = hdkey
  .derive("m/44'/60'/0'/0")
  .deriveChild(0);

const privateKey = child.privateKey;
const publicKey = child.publicKey;

BIP-39 助记词

import { generateMnemonic, validateMnemonic } from '@scure/bip39';
import { wordlist } from '@scure/bip39/wordlists/english';

// 生成新助记词(128位 = 12个单词,256位 = 24个单词)
const mnemonic = generateMnemonic(wordlist, 256);

// 验证助记词
const isValid = validateMnemonic(mnemonic, wordlist);

秘密共享

Shamir秘密共享

import { split, combine } from 'shamir-secret-sharing';

// 将秘密分割为5份,需要3份才能重构
const shares = await split(secretBytes, 5, 3);

// 使用任意3份重构
const reconstructed = await combine([shares[0], shares[2], shares[4]]);

Feldman VSS(可验证秘密共享)

// 承诺允许在不泄露秘密的情况下验证
const { shares, commitments } = feldmanVSS.split(secret, n, t);

// 验证份额
const isValidShare = feldmanVSS.verifyShare(share, commitments);

哈希函数

以太坊专用

import { keccak_256 } from '@noble/hashes/sha3';

// 从公钥生成以太坊地址
const publicKeyHash = keccak_256(publicKey.slice(1)); // 移除0x04前缀
const address = '0x' + publicKeyHash.slice(-20).toString('hex');

ZK友好哈希

// Poseidon哈希(用于ZK电路)
import { poseidon } from '@iden3/js-crypto';

const hash = poseidon([input1, input2, input3]);

// MiMC哈希
import { mimcSponge } from 'circomlib';

const hash = mimcSponge.multiHash([input1, input2], key, numOutputs);

承诺方案

Pedersen承诺

// commit(m, r) = g^m * h^r
// 隐藏性:无法从承诺确定m
// 绑定性:无法找到m', r'使得commit(m, r) = commit(m', r')

function pedersenCommit(m, r, g, h) {
  return g.multiply(m).add(h.multiply(r));
}

// 验证承诺
function verifyCommitment(commitment, m, r, g, h) {
  const expected = pedersenCommit(m, r, g, h);
  return commitment.equals(expected);
}

哈希承诺

// 简单的提交-揭示方案
function commit(value, nonce) {
  return keccak256(abi.encodePacked(value, nonce));
}

function reveal(commitment, value, nonce) {
  return commitment === keccak256(abi.encodePacked(value, nonce));
}

恒定时间操作

对安全至关重要

// 错误:易受时序攻击
function compareInsecure(a, b) {
  return a === b; // 在第一个不匹配处短路
}

// 正确:恒定时间比较
function compareSecure(a, b) {
  if (a.length !== b.length) return false;
  let diff = 0;
  for (let i = 0; i < a.length; i++) {
    diff |= a[i] ^ b[i];
  }
  return diff === 0;
}

库函数

import { timingSafeEqual } from 'crypto';

// 使用内置的恒定时间比较
const isEqual = timingSafeEqual(Buffer.from(a), Buffer.from(b));

安全随机性

CSPRNG使用

import { randomBytes } from '@noble/hashes/utils';

// 生成安全随机字节
const privateKey = randomBytes(32);

// 用于浏览器环境
const array = new Uint8Array(32);
crypto.getRandomValues(array);

Chainlink VRF(链上)

// 在链上请求随机性
function requestRandomness() external returns (uint256 requestId) {
    return COORDINATOR.requestRandomWords(
        keyHash,
        subscriptionId,
        requestConfirmations,
        callbackGasLimit,
        numWords
    );
}

function fulfillRandomWords(uint256, uint256[] memory randomWords) internal override {
    // 使用randomWords[0]获取可证明公平的随机性
}

流程集成

此技能与以下集成:

  • cryptographic-protocol-implementation.js - 完整协议设计
  • hd-wallet-implementation.js - 钱包密钥管理
  • multi-signature-wallet.js - 多重签名方案
  • threshold-signature-scheme.js - TSS实现
  • zk-circuit-development.js - ZK友好原语

安全指南

应做事项

  • 使用经过审计的密码学库(noble-curves、libsodium)
  • 对秘密比较使用恒定时间操作
  • 安全生成和处理熵
  • 使用后从内存中清除敏感数据
  • 使用适当的密钥长度(AES为256位,secp256k1)

禁止事项

  • 从头开始实现密码算法
  • 对安全关键操作使用Math.random()
  • 以明文存储私钥
  • 在签名方案中重用随机数
  • 记录或暴露秘密材料

推荐库

用途 URL
@noble/curves 椭圆曲线(secp256k1、ed25519、BLS12-381) noble-curves
@noble/hashes 哈希函数(SHA、Keccak、BLAKE) noble-hashes
@scure/bip32 HD密钥派生 scure-bip32
@scure/bip39 助记词生成 scure-bip39
libsodium 通用密码学 libsodium.js
circomlibjs ZK友好密码学 circomlibjs

另请参阅

  • agents/crypto-engineer/AGENT.md - 密码学实现专家
  • skills/zk-circuits/SKILL.md - 零知识证明电路
  • references.md - 外部密码学参考资料