bls 签名
JavaScript 库,用于以聚合方式执行 BLS 签名 Boneh, Drijvers, Neven 2018 (英语),使用后遗症工具包用于密码原始物(pirings,EC,hashing).
这个库是一个 JavaScript 端口 Chia 网络的 BLS lib。我们也有打字功能,所以您也可以使用 TypeScript !
使用量
npm i bls-signatures --save # or yarn add bls-signatures
创建密钥和签名
var loadBls = require("bls-signatures");
var BLS = await loadBls();
var seed = Uint8Array.from([
0, 50, 6, 244, 24, 199, 1, 25, 52, 88, 192,
19, 18, 12, 89, 6, 220, 18, 102, 58, 209, 82,
12, 62, 89, 110, 182, 9, 44, 20, 254, 22
]);
var sk = BLS.AugSchemeMPL.key_gen(seed);
var pk = sk.get_g1();
var message = Uint8Array.from([1,2,3,4,5]);
var signature = BLS.AugSchemeMPL.sign(sk, message);
let ok = BLS.AugSchemeMPL.verify(pk, message, signature);
console.log(ok); // true
将密钥和签名序列化到字节
var skBytes = sk.serialize();
var pkBytes = pk.serialize();
var signatureBytes = signature.serialize();
console.log(BLS.Util.hex_str(skBytes));
console.log(BLS.Util.hex_str(pkBytes));
console.log(BLS.Util.hex_str(signatureBytes));
从字节装入密钥和签名
var skc = BLS.PrivateKey.from_bytes(skBytes, false);
var pk = BLS.G1Element.from_bytes(pkBytes);
var signature = BLS.G2Element.from_bytes(signatureBytes);
创建汇总签名
// Generate some more private keys
seed[0] = 1;
var sk1 = BLS.AugSchemeMPL.key_gen(seed);
seed[0] = 2;
var sk2 = BLS.AugSchemeMPL.key_gen(seed);
var message2 = Uint8Array.from([1,2,3,4,5,6,7]);
// Generate first sig
var pk1 = sk1.get_g1();
var sig1 = BLS.AugSchemeMPL.sign(sk1, message);
// Generate second sig
var pk2 = sk2.get_g1();
var sig2 = BLS.AugSchemeMPL.sign(sk2, message2);
// Signatures can be non-interactively combined by anyone
var aggSig = BLS.AugSchemeMPL.aggregate([sig1, sig2]);
ok = BLS.AugSchemeMPL.aggregate_verify([pk1, pk2], [message, message2], aggSig);
console.log(ok); // true
任意的总量树
seed[0] = 3;
var sk3 = BLS.AugSchemeMPL.key_gen(seed);
var pk3 = sk3.get_g1();
var message3 = Uint8Array.from([100, 2, 254, 88, 90, 45, 23]);
var sig3 = BLS.AugSchemeMPL.sign(sk3, message3);
var aggSigFinal = BLS.AugSchemeMPL.aggregate([aggSig, sig3]);
ok = BLS.AugSchemeMPL.aggregate_verify([pk1, pk2, pk3], [message, message2, message3], aggSigFinal);
console.log(ok); // true
快速核查持有证明计划
// If the same message is signed, you can use Proof of Posession (PopScheme) for efficiency
// A proof of possession MUST be passed around with the PK to ensure security.
var popSig1 = BLS.PopSchemeMPL.sign(sk1, message);
var popSig2 = BLS.PopSchemeMPL.sign(sk2, message);
var popSig3 = BLS.PopSchemeMPL.sign(sk3, message);
var pop1 = BLS.PopSchemeMPL.pop_prove(sk1);
var pop2 = BLS.PopSchemeMPL.pop_prove(sk2);
var pop3 = BLS.PopSchemeMPL.pop_prove(sk3);
ok = BLS.PopSchemeMPL.pop_verify(pk1, pop1);
console.log(ok); // true
ok = BLS.PopSchemeMPL.pop_verify(pk2, pop2);
console.log(ok); // true
ok = BLS.PopSchemeMPL.pop_verify(pk3, pop3);
console.log(ok); // true
var popSigAgg = BLS.PopSchemeMPL.aggregate([popSig1, popSig2, popSig3]);
ok = BLS.PopSchemeMPL.fast_aggregate_verify([pk1, pk2, pk3], message, popSigAgg);
console.log(ok); // true
// Aggregate public key, indistinguishable from a single public key
var popAggPk = pk1.add(pk2).add(pk3);
ok = BLS.PopSchemeMPL.verify(popAggPk, message, popSigAgg);
console.log(ok); // true
// Aggregate private keys
var aggSk = BLS.PrivateKey.aggregate([sk1, sk2, sk3]);
ok = (BLS.PopSchemeMPL.sign(aggSk, message).equal_to(popSigAgg));
console.log(ok); // true
使用 HD 密钥 EIP-2333
// You can derive 'child' keys from any key, to create arbitrary trees. 4 byte indeces are used.
// Hardened (more secure, but no parent pk -> child pk)
var masterSk = BLS.AugSchemeMPL.key_gen(seed);
var child = BLS.AugSchemeMPL.derive_child_sk(masterSk, 152);
var grandChild = BLS.AugSchemeMPL.derive_child_sk(child, 952);
// Unhardened (less secure, but can go from parent pk -> child pk), BIP32 style
var masterPk = masterSk.get_g1();
var childU = BLS.AugSchemeMPL.derive_child_sk_unhardened(masterSk, 22);
var grandchildU = BLS.AugSchemeMPL.derive_child_sk_unhardened(childU, 0);
var childUPk = BLS.AugSchemeMPL.derive_child_pk_unhardened(masterPk, 22);
var grandchildUPk = BLS.AugSchemeMPL.derive_child_pk_unhardened(childUPk, 0);
ok = (grandchildUPk.equal_to(grandchildU.get_g1()));
console.log(ok); // true
请参考图书馆的 输入 详细API信息。 使用大小写可在 原始的lib读取器。 。 。 .
关于使用的重要说明: 由于这个库是c++库的WebAssembly端口,JavaScript的自动内存管理无法使用. 如以下示例所示,如果不再需要所有对象,请通过调用这些对象的删除方法,手工删除所有对象.
sk.delete();
// ...
pk.delete();
// ...
sig1.delete();
// ...
构建
建筑需要Node.js(含npm)和 标记 将安装. 构建过程与 c++ lib 相同, 附加一个步骤: 通过 Emscripten 工具链文件作为 CMake 的选项 . 从工程根目录中运行 :
#git submodule update --init --recursive
mkdir js_build
cd js_build
cmake ../ -DCMAKE_TOOLCHAIN_FILE={path_to_your_emscripten_installation}/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake
cmake --build . --
在对库进行修改后运行构建,包括readme和测试,因为库将从构建目录中部署,而构建系统会复制所有来自源目录的文件.
运行测试
测试在节点.js和Firefox运行,因此需要安装节点.js和Firefox.
进行测试,建立图书馆,然后去 js_bindings 创建目录中的文件夹并运行
npm test