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