LCOV - code coverage report
Current view: top level - src/bls - bls_wrapper.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 201 234 85.9 %
Date: 2026-08-09 10:51:41 Functions: 23 25 92.0 %

          Line data    Source code
       1             : // Copyright (c) 2018 The Dash Core developers
       2             : // Copyright (c) 2021 The PIVX Core developers
       3             : // Distributed under the MIT software license, see the accompanying
       4             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       5             : 
       6             : #include "bls/bls_wrapper.h"
       7             : 
       8             : #include "random.h"
       9             : #include "tinyformat.h"
      10             : 
      11             : #ifndef BUILD_BITCOIN_INTERNAL
      12             : #include "support/allocators/mt_pooled_secure.h"
      13             : #endif
      14             : 
      15             : #include <assert.h>
      16             : #include <string.h>
      17             : 
      18             : static std::unique_ptr<bls::CoreMPL> pScheme(new bls::BasicSchemeMPL);
      19             : 
      20          40 : CBLSId::CBLSId(const uint256& nHash) : CBLSWrapper<CBLSIdImplicit, BLS_CURVE_ID_SIZE, CBLSId>()
      21             : {
      22          40 :     impl = nHash;
      23          40 :     fValid = true;
      24          40 :     cachedHash.SetNull();
      25          40 : }
      26             : 
      27        1560 : void CBLSSecretKey::AggregateInsecure(const CBLSSecretKey& o)
      28             : {
      29        1560 :     assert(IsValid() && o.IsValid());
      30        4680 :     impl = bls::PrivateKey::Aggregate({impl, o.impl});
      31        1560 :     cachedHash.SetNull();
      32        1560 : }
      33             : 
      34           5 : CBLSSecretKey CBLSSecretKey::AggregateInsecure(const std::vector<CBLSSecretKey>& sks)
      35             : {
      36           5 :     if (sks.empty()) {
      37           5 :         return CBLSSecretKey();
      38             :     }
      39             : 
      40           5 :     std::vector<bls::PrivateKey> v;
      41           5 :     v.reserve(sks.size());
      42          17 :     for (auto& sk : sks) {
      43          12 :         v.emplace_back(sk.impl);
      44             :     }
      45             : 
      46          10 :     CBLSSecretKey ret;
      47           5 :     ret.impl = bls::PrivateKey::Aggregate(v);
      48           5 :     ret.fValid = true;
      49           5 :     ret.cachedHash.SetNull();
      50           5 :     return ret;
      51             : }
      52             : 
      53             : #ifndef BUILD_BITCOIN_INTERNAL
      54        1382 : void CBLSSecretKey::MakeNewKey()
      55             : {
      56        3079 :     unsigned char buf[32];
      57        3079 :     while (true) {
      58        3079 :         GetStrongRandBytes(buf, sizeof(buf));
      59        3079 :         try {
      60        3079 :             impl = bls::PrivateKey::FromBytes(bls::Bytes((const uint8_t*)buf, SerSize));
      61        1382 :             break;
      62        1697 :         } catch (...) {
      63             :         }
      64             :     }
      65        1382 :     fValid = true;
      66        1382 :     cachedHash.SetNull();
      67        1382 : }
      68             : #endif
      69             : 
      70        1600 : bool CBLSSecretKey::SecretKeyShare(const std::vector<CBLSSecretKey>& msk, const CBLSId& _id)
      71             : {
      72        1600 :     fValid = false;
      73        1600 :     cachedHash.SetNull();
      74             : 
      75        1600 :     if (!_id.IsValid()) {
      76             :         return false;
      77             :     }
      78             : 
      79        3200 :     std::vector<bls::PrivateKey> mskVec;
      80        1600 :     mskVec.reserve(msk.size());
      81       49600 :     for (const CBLSSecretKey& sk : msk) {
      82       48000 :         if (!sk.IsValid()) {
      83           0 :             return false;
      84             :         }
      85       48000 :         mskVec.emplace_back(sk.impl);
      86             :     }
      87             : 
      88        1600 :     try {
      89        1600 :         impl = bls::Threshold::PrivateKeyShare(mskVec, bls::Bytes(_id.impl.begin(), _id.impl.size()));
      90           0 :     } catch (...) {
      91           0 :         return false;
      92             :     }
      93             : 
      94        1600 :     fValid = true;
      95        1600 :     cachedHash.SetNull();
      96        1600 :     return true;
      97             : }
      98             : 
      99        4643 : CBLSPublicKey CBLSSecretKey::GetPublicKey() const
     100             : {
     101        4643 :     if (!IsValid()) {
     102           0 :         return CBLSPublicKey();
     103             :     }
     104             : 
     105        4643 :     CBLSPublicKey pubKey;
     106        4643 :     pubKey.impl = impl.GetG1Element();
     107        4643 :     pubKey.fValid = true;
     108        4643 :     pubKey.cachedHash.SetNull();
     109        4643 :     return pubKey;
     110             : }
     111             : 
     112         111 : CBLSSignature CBLSSecretKey::Sign(const uint256& hash) const
     113             : {
     114         111 :     if (!IsValid()) {
     115           0 :         return CBLSSignature();
     116             :     }
     117             : 
     118         111 :     CBLSSignature sigRet;
     119         111 :     sigRet.impl = pScheme->Sign(impl, bls::Bytes(hash.begin(), hash.size()));
     120             : 
     121         111 :     sigRet.fValid = true;
     122         111 :     sigRet.cachedHash.SetNull();
     123             : 
     124         111 :     return sigRet;
     125             : }
     126             : 
     127           1 : bool CBLSSecretKey::Recover(const std::vector<CBLSSecretKey>& keys, const std::vector<CBLSId>& ids)
     128             : {
     129           1 :     fValid = false;
     130           1 :     cachedHash.SetNull();
     131             : 
     132           1 :     if (keys.empty() || ids.empty() || keys.size() != ids.size()) {
     133             :         return false;
     134             :     }
     135             : 
     136           1 :     std::vector<bls::PrivateKey> keysVec;
     137           1 :     std::vector<bls::Bytes> idsVec;
     138           1 :     keysVec.reserve(keys.size());
     139           1 :     idsVec.reserve(keys.size());
     140             : 
     141          31 :     for (size_t i = 0; i < keys.size(); i++) {
     142          30 :         if (!keys[i].IsValid() || !ids[i].IsValid()) {
     143             :             return false;
     144             :         }
     145          30 :         keysVec.emplace_back(keys[i].impl);
     146          30 :         idsVec.emplace_back(ids[i].impl.begin(), ids[i].impl.size());
     147             :     }
     148             : 
     149           1 :     try {
     150           1 :         impl = bls::Threshold::PrivateKeyRecover(keysVec, idsVec);
     151           0 :     } catch (...) {
     152           0 :         return false;
     153             :     }
     154             : 
     155           1 :     fValid = true;
     156           1 :     cachedHash.SetNull();
     157           1 :     return true;
     158             : }
     159             : 
     160        2768 : void CBLSPublicKey::AggregateInsecure(const CBLSPublicKey& o)
     161             : {
     162        2768 :     assert(IsValid() && o.IsValid());
     163        2768 :     impl = pScheme->Aggregate({impl, o.impl});
     164        2768 :     cachedHash.SetNull();
     165        2768 : }
     166             : 
     167           5 : CBLSPublicKey CBLSPublicKey::AggregateInsecure(const std::vector<CBLSPublicKey>& pks)
     168             : {
     169           5 :     if (pks.empty()) {
     170           5 :         return CBLSPublicKey();
     171             :     }
     172             : 
     173          10 :     std::vector<bls::G1Element> vecPublicKeys;
     174           5 :     vecPublicKeys.reserve(pks.size());
     175          17 :     for (auto& pk : pks) {
     176          12 :         vecPublicKeys.emplace_back(pk.impl);
     177             :     }
     178             : 
     179           5 :     CBLSPublicKey ret;
     180           5 :     ret.impl = pScheme->Aggregate(vecPublicKeys);
     181           5 :     ret.fValid = true;
     182           5 :     ret.cachedHash.SetNull();
     183           5 :     return ret;
     184             : }
     185             : 
     186        3200 : bool CBLSPublicKey::PublicKeyShare(const std::vector<CBLSPublicKey>& mpk, const CBLSId& _id)
     187             : {
     188        3200 :     fValid = false;
     189        3200 :     cachedHash.SetNull();
     190             : 
     191        3200 :     if (!_id.IsValid()) {
     192             :         return false;
     193             :     }
     194             : 
     195        6400 :     std::vector<bls::G1Element> mpkVec;
     196        3200 :     mpkVec.reserve(mpk.size());
     197       99200 :     for (const CBLSPublicKey& pk : mpk) {
     198       96000 :         if (!pk.IsValid()) {
     199           0 :             return false;
     200             :         }
     201       96000 :         mpkVec.emplace_back(pk.impl);
     202             :     }
     203             : 
     204        3200 :     try {
     205        3200 :         impl = bls::Threshold::PublicKeyShare(mpkVec, bls::Bytes(_id.impl.begin(), _id.impl.size()));
     206           0 :     } catch (...) {
     207           0 :         return false;
     208             :     }
     209             : 
     210        3200 :     fValid = true;
     211        3200 :     cachedHash.SetNull();
     212        3200 :     return true;
     213             : }
     214             : 
     215        3206 : bool CBLSPublicKey::DHKeyExchange(const CBLSSecretKey& sk, const CBLSPublicKey& pk)
     216             : {
     217        3206 :     fValid = false;
     218        3206 :     cachedHash.SetNull();
     219             : 
     220        3206 :     if (!sk.IsValid() || !pk.IsValid()) {
     221             :         return false;
     222             :     }
     223        3206 :     impl = sk.impl * pk.impl;
     224        3206 :     fValid = true;
     225        3206 :     cachedHash.SetNull();
     226        3206 :     return true;
     227             : }
     228             : 
     229         162 : void CBLSSignature::AggregateInsecure(const CBLSSignature& o)
     230             : {
     231         162 :     assert(IsValid() && o.IsValid());
     232         162 :     impl = pScheme->Aggregate({impl, o.impl});
     233         162 :     cachedHash.SetNull();
     234         162 : }
     235             : 
     236           0 : CBLSSignature CBLSSignature::AggregateInsecure(const std::vector<CBLSSignature>& sigs)
     237             : {
     238           0 :     if (sigs.empty()) {
     239           0 :         return CBLSSignature();
     240             :     }
     241             : 
     242           0 :     std::vector<bls::G2Element> v;
     243           0 :     v.reserve(sigs.size());
     244           0 :     for (auto& pk : sigs) {
     245           0 :         v.emplace_back(pk.impl);
     246             :     }
     247             : 
     248           0 :     CBLSSignature ret;
     249           0 :     ret.impl = pScheme->Aggregate(v);
     250           0 :     ret.fValid = true;
     251           0 :     ret.cachedHash.SetNull();
     252           0 :     return ret;
     253             : }
     254             : 
     255           5 : CBLSSignature CBLSSignature::AggregateSecure(const std::vector<CBLSSignature>& sigs,
     256             :                                              const std::vector<CBLSPublicKey>& pks,
     257             :                                              const uint256& hash)
     258             : {
     259           5 :     if (sigs.size() != pks.size() || sigs.empty()) {
     260           5 :         return CBLSSignature();
     261             :     }
     262             : 
     263          10 :     std::vector<bls::G1Element> vecPublicKeys;
     264           5 :     vecPublicKeys.reserve(pks.size());
     265          17 :     for (auto& pk : pks) {
     266          12 :         vecPublicKeys.push_back(pk.impl);
     267             :     }
     268             : 
     269          10 :     std::vector<bls::G2Element> vecSignatures;
     270           5 :     vecSignatures.reserve(pks.size());
     271          17 :     for (auto& sig : sigs) {
     272          12 :         vecSignatures.push_back(sig.impl);
     273             :     }
     274             : 
     275           5 :     CBLSSignature ret;
     276           5 :     ret.impl = pScheme->AggregateSecure(vecPublicKeys, vecSignatures, bls::Bytes(hash.begin(), hash.size()));
     277           5 :     ret.fValid = true;
     278           5 :     ret.cachedHash.SetNull();
     279           5 :     return ret;
     280             : }
     281             : 
     282           0 : void CBLSSignature::SubInsecure(const CBLSSignature& o)
     283             : {
     284           0 :     assert(IsValid() && o.IsValid());
     285           0 :     impl = impl + o.impl.Negate();
     286           0 :     cachedHash.SetNull();
     287           0 : }
     288             : 
     289         109 : bool CBLSSignature::VerifyInsecure(const CBLSPublicKey& pubKey, const uint256& hash) const
     290             : {
     291         109 :     if (!IsValid() || !pubKey.IsValid()) {
     292             :         return false;
     293             :     }
     294             : 
     295         109 :     try {
     296         109 :         return pScheme->Verify(pubKey.impl, bls::Bytes(hash.begin(), hash.size()), impl);
     297           0 :     } catch (...) {
     298           0 :         return false;
     299             :     }
     300             : }
     301             : 
     302         128 : bool CBLSSignature::VerifyInsecureAggregated(const std::vector<CBLSPublicKey>& pubKeys, const std::vector<uint256>& hashes) const
     303             : {
     304         128 :     if (!IsValid()) {
     305             :         return false;
     306             :     }
     307         128 :     assert(!pubKeys.empty() && !hashes.empty() && pubKeys.size() == hashes.size());
     308             : 
     309         256 :     std::vector<bls::G1Element> pubKeyVec;
     310         128 :     std::vector<bls::Bytes> hashes2;
     311         128 :     hashes2.reserve(hashes.size());
     312         128 :     pubKeyVec.reserve(pubKeys.size());
     313         380 :     for (size_t i = 0; i < pubKeys.size(); i++) {
     314         252 :         auto& p = pubKeys[i];
     315         252 :         if (!p.IsValid()) {
     316             :             return false;
     317             :         }
     318         252 :         pubKeyVec.push_back(p.impl);
     319         252 :         hashes2.emplace_back(hashes[i].begin(), hashes[i].size());
     320             :     }
     321             : 
     322         128 :     try {
     323         128 :         return pScheme->AggregateVerify(pubKeyVec, hashes2, impl);
     324           0 :     } catch (...) {
     325           0 :         return false;
     326             :     }
     327             : }
     328             : 
     329          14 : bool CBLSSignature::VerifySecureAggregated(const std::vector<CBLSPublicKey>& pks, const uint256& hash) const
     330             : {
     331          14 :     if (pks.empty()) {
     332             :         return false;
     333             :     }
     334             : 
     335          28 :     std::vector<bls::G1Element> vecPublicKeys;
     336          14 :     vecPublicKeys.reserve(pks.size());
     337          47 :     for (const auto& pk : pks) {
     338          33 :         vecPublicKeys.push_back(pk.impl);
     339             :     }
     340             : 
     341          14 :     return pScheme->VerifySecure(vecPublicKeys, impl, bls::Bytes(hash.begin(), hash.size()));
     342             : }
     343             : 
     344           2 : bool CBLSSignature::Recover(const std::vector<CBLSSignature>& sigs, const std::vector<CBLSId>& ids)
     345             : {
     346           2 :     fValid = false;
     347           2 :     cachedHash.SetNull();
     348             : 
     349           2 :     if (sigs.empty() || ids.empty() || sigs.size() != ids.size()) {
     350             :         return false;
     351             :     }
     352             : 
     353           4 :     std::vector<bls::G2Element> sigsVec;
     354           2 :     std::vector<bls::Bytes> idsVec;
     355           2 :     sigsVec.reserve(sigs.size());
     356           2 :     idsVec.reserve(sigs.size());
     357             : 
     358          62 :     for (size_t i = 0; i < sigs.size(); i++) {
     359          60 :         if (!sigs[i].IsValid() || !ids[i].IsValid()) {
     360             :             return false;
     361             :         }
     362          60 :         sigsVec.emplace_back(sigs[i].impl);
     363          60 :         idsVec.emplace_back(ids[i].impl.begin(), ids[i].impl.size());
     364             :     }
     365             : 
     366           2 :     try {
     367           2 :         impl = bls::Threshold::SignatureRecover(sigsVec, idsVec);
     368           0 :     } catch (...) {
     369           0 :         return false;
     370             :     }
     371             : 
     372           2 :     fValid = true;
     373           2 :     cachedHash.SetNull();
     374           2 :     return true;
     375             : }
     376             : 
     377             : #ifndef BUILD_BITCOIN_INTERNAL
     378             : 
     379             : static std::once_flag init_flag;
     380             : static mt_pooled_secure_allocator<uint8_t>* secure_allocator_instance;
     381          25 : static void create_secure_allocator()
     382             : {
     383             :     // make sure LockedPoolManager is initialized first (ensures destruction order)
     384          25 :     LockedPoolManager::Instance();
     385             : 
     386             :     // static variable in function scope ensures it's initialized when first accessed
     387             :     // and destroyed before LockedPoolManager
     388          25 :     static mt_pooled_secure_allocator<uint8_t> a(sizeof(bn_t) + sizeof(size_t));
     389          25 :     secure_allocator_instance = &a;
     390          25 : }
     391             : 
     392      717148 : static mt_pooled_secure_allocator<uint8_t>& get_secure_allocator()
     393             : {
     394      717148 :     std::call_once(init_flag, create_secure_allocator);
     395      717148 :     return *secure_allocator_instance;
     396             : }
     397             : 
     398      358574 : static void* secure_allocate(size_t n)
     399             : {
     400      358574 :     uint8_t* ptr = get_secure_allocator().allocate(n + sizeof(size_t));
     401      358574 :     *(size_t*)ptr = n;
     402      358574 :     return ptr + sizeof(size_t);
     403             : }
     404             : 
     405      358574 : static void secure_free(void* p)
     406             : {
     407      358574 :     if (!p) {
     408             :         return;
     409             :     }
     410             : 
     411      358574 :     uint8_t* ptr = (uint8_t*)p - sizeof(size_t);
     412      358574 :     size_t n = *(size_t*)ptr;
     413      358574 :     return get_secure_allocator().deallocate(ptr, n);
     414             : }
     415             : #endif
     416             : 
     417         731 : bool BLSInit()
     418             : {
     419         731 :     if (!bls::BLS::Init()) {
     420             :         return false;
     421             :     }
     422             : #ifndef BUILD_BITCOIN_INTERNAL
     423         731 :     bls::BLS::SetSecureAllocator(secure_allocate, secure_free);
     424             : #endif
     425         731 :     return true;
     426             : }

Generated by: LCOV version 1.14