Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Explore the `examples` folder for more detailed usage scenarios.
For local development, you can install the package in editable mode, which allows you to make changes and test them immediately:

```bash
python3 -m pip install .
python3 -m pip install -e .
```

After making changes, it's important to ensure all tests pass by running:
Expand Down
27 changes: 27 additions & 0 deletions examples/example_bls_threshold.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from pactus.crypto.bls.private_key import PrivateKey


# Example of BLS threshold signature aggregation using Shamir's Secret Sharing
# This example demonstrates how to create a threshold signature scheme
# where a subset of signers can create a valid signature.


def main() -> None:
# msg = "some message".encode()
N = 3 # Number of signers
T = 2 # Threshold for aggregation

msk = PrivateKey.random() # Master Secret Key
mpk = msk.public_key()

print(f"Master Secret Key: {msk.raw_bytes().hex()}")
print(f"Master Public Key: {mpk.string()}")

shares = msk.split(N, T)

for i, sk in enumerate(shares):
print(f"Private Key Share {i + 1}: {sk.raw_bytes().hex()}")


if __name__ == "__main__":
main()
27 changes: 27 additions & 0 deletions pactus/crypto/bls/private_key.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,30 @@ def public_key(self) -> PublicKey:
def sign(self, msg: bytes) -> Signature:
point_g1 = sign(self.scalar, msg, ciphersuite=DST)
return Signature(point_g1)

def split(self, n: int, t: int) -> list[PrivateKey]:
if n < t:
msg = f"n must be greater than t: n={n}, t={t}"
raise ValueError(msg)

if n < 1:
msg = f"n must be greater than 1: n={n}"
raise ValueError(msg)

# Create the coefficients for the polynomial: c[0] = secret, c[1..t-1] = random private keys
coeffs = [self.scalar]
for _ in range(1, t):
rand_priv = PrivateKey.random()
coeffs.append(rand_priv.scalar)

# Generate n shares by evaluating the polynomial at x = 1..n
shares = []
for i in range(1, n + 1):
share_scalar = utils.evaluate_polynomial(coeffs, i, curve_order)
if share_scalar is None:
msg = f"Failed to evaluate polynomial at x={i}"
raise ValueError(msg)

shares.append(PrivateKey(share_scalar))

return shares
Loading