Skip to content

Commit e169a61

Browse files
authored
Merge pull request #2084 from theStack/bip374-vendor-secp256k1lab
BIP-374: vendor secp256k1lab and use it for reference implementation
2 parents 3177af3 + 2b7f079 commit e169a61

File tree

17 files changed

+442
-127
lines changed

17 files changed

+442
-127
lines changed

bip-0374.mediawiki

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,10 @@ This proposal is compatible with all older clients.
116116
== Test Vectors and Reference Code ==
117117

118118
A reference python implementation is included [https://github.com/bitcoin/bips/blob/master/bip-0374/reference.py here].
119+
It uses a vendored copy of the [https://github.com/secp256k1lab/secp256k1lab/ secp256k1lab] library at version 1.0.0
120+
(commit [https://github.com/secp256k1lab/secp256k1lab/commit/44dc4bd893b8f03e621585e3bf255253e0e0fbfb
121+
44dc4bd893b8f03e621585e3bf255253e0e0fbfb]).
122+
119123
Test vectors can be generated by running <code>./bip-0374/gen_test_vectors.py</code> which will produce a CSV file of random test vectors for both generating and verifying proofs. These can be run against the reference implementation with <code>./bip-0374/run_test_vectors.py</code>.
120124

121125
== Changelog ==

bip-0374/gen_test_vectors.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,29 @@
11
#!/usr/bin/env python3
22
"""Generate the BIP-0374 test vectors."""
33
import csv
4-
import os
5-
import sys
4+
from pathlib import Path
65
from reference import (
7-
TaggedHash,
86
dleq_generate_proof,
97
dleq_verify_proof,
108
)
11-
from secp256k1 import G as GENERATOR, GE
9+
from secp256k1lab.secp256k1 import G as GENERATOR, GE
10+
from secp256k1lab.util import tagged_hash
1211

1312

1413
NUM_SUCCESS_TEST_VECTORS = 8
1514
DLEQ_TAG_TESTVECTORS_RNG = "BIP0374/testvectors_rng"
1615

17-
FILENAME_GENERATE_PROOF_TEST = os.path.join(sys.path[0], 'test_vectors_generate_proof.csv')
18-
FILENAME_VERIFY_PROOF_TEST = os.path.join(sys.path[0], 'test_vectors_verify_proof.csv')
16+
FILENAME_GENERATE_PROOF_TEST = Path(__file__).parent / 'test_vectors_generate_proof.csv'
17+
FILENAME_VERIFY_PROOF_TEST = Path(__file__).parent / 'test_vectors_verify_proof.csv'
1918

2019

2120
def random_scalar_int(vector_i, purpose):
22-
rng_out = TaggedHash(DLEQ_TAG_TESTVECTORS_RNG, purpose.encode() + vector_i.to_bytes(4, 'little'))
21+
rng_out = tagged_hash(DLEQ_TAG_TESTVECTORS_RNG, purpose.encode() + vector_i.to_bytes(4, 'little'))
2322
return int.from_bytes(rng_out, 'big') % GE.ORDER
2423

2524

2625
def random_bytes(vector_i, purpose):
27-
rng_out = TaggedHash(DLEQ_TAG_TESTVECTORS_RNG, purpose.encode() + vector_i.to_bytes(4, 'little'))
26+
rng_out = tagged_hash(DLEQ_TAG_TESTVECTORS_RNG, purpose.encode() + vector_i.to_bytes(4, 'little'))
2827
return rng_out
2928

3029

bip-0374/reference.py

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,38 +2,30 @@
22

33
"""Reference implementation of DLEQ BIP for secp256k1 with unit tests."""
44

5-
from hashlib import sha256
5+
from pathlib import Path
66
import random
7-
from secp256k1 import G, GE
87
import sys
98
import unittest
109

10+
# Prefer the vendored copy of secp256k1lab
11+
sys.path.insert(0, str(Path(__file__).parent / "secp256k1lab/src"))
12+
from secp256k1lab.secp256k1 import G, GE
13+
from secp256k1lab.util import tagged_hash, xor_bytes
14+
1115

1216
DLEQ_TAG_AUX = "BIP0374/aux"
1317
DLEQ_TAG_NONCE = "BIP0374/nonce"
1418
DLEQ_TAG_CHALLENGE = "BIP0374/challenge"
1519

1620

17-
def TaggedHash(tag: str, data: bytes) -> bytes:
18-
ss = sha256(tag.encode()).digest()
19-
ss += ss
20-
ss += data
21-
return sha256(ss).digest()
22-
23-
24-
def xor_bytes(lhs: bytes, rhs: bytes) -> bytes:
25-
assert len(lhs) == len(rhs)
26-
return bytes([lhs[i] ^ rhs[i] for i in range(len(lhs))])
27-
28-
2921
def dleq_challenge(
3022
A: GE, B: GE, C: GE, R1: GE, R2: GE, m: bytes | None, G: GE,
3123
) -> int:
3224
if m is not None:
3325
assert len(m) == 32
3426
m = bytes([]) if m is None else m
3527
return int.from_bytes(
36-
TaggedHash(
28+
tagged_hash(
3729
DLEQ_TAG_CHALLENGE,
3830
A.to_bytes_compressed()
3931
+ B.to_bytes_compressed()
@@ -59,9 +51,9 @@ def dleq_generate_proof(
5951
assert len(m) == 32
6052
A = a * G
6153
C = a * B
62-
t = xor_bytes(a.to_bytes(32, "big"), TaggedHash(DLEQ_TAG_AUX, r))
54+
t = xor_bytes(a.to_bytes(32, "big"), tagged_hash(DLEQ_TAG_AUX, r))
6355
m_prime = bytes([]) if m is None else m
64-
rand = TaggedHash(
56+
rand = tagged_hash(
6557
DLEQ_TAG_NONCE, t + A.to_bytes_compressed() + C.to_bytes_compressed() + m_prime
6658
)
6759
k = int.from_bytes(rand, "big") % GE.ORDER

bip-0374/run_test_vectors.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
#!/usr/bin/env python3
22
"""Run the BIP-DLEQ test vectors."""
33
import csv
4-
import os
4+
from pathlib import Path
55
import sys
66
from reference import (
77
dleq_generate_proof,
88
dleq_verify_proof,
99
)
10-
from secp256k1 import GE
10+
from secp256k1lab.secp256k1 import GE
1111

1212

13-
FILENAME_GENERATE_PROOF_TEST = os.path.join(sys.path[0], 'test_vectors_generate_proof.csv')
14-
FILENAME_VERIFY_PROOF_TEST = os.path.join(sys.path[0], 'test_vectors_verify_proof.csv')
13+
FILENAME_GENERATE_PROOF_TEST = Path(__file__).parent / 'test_vectors_generate_proof.csv'
14+
FILENAME_VERIFY_PROOF_TEST = Path(__file__).parent / 'test_vectors_verify_proof.csv'
1515

1616

1717
all_passed = True
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
name: Tests
2+
on: [push, pull_request]
3+
jobs:
4+
ruff:
5+
runs-on: ubuntu-latest
6+
steps:
7+
- uses: actions/checkout@v4
8+
- name: Install the latest version of uv
9+
uses: astral-sh/setup-uv@v5
10+
- run: uvx ruff check .
11+
mypy:
12+
runs-on: ubuntu-latest
13+
steps:
14+
- uses: actions/checkout@v4
15+
- name: Install the latest version of uv
16+
uses: astral-sh/setup-uv@v5
17+
- run: uvx mypy .
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
3.9

bip-0374/secp256k1lab/CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Changelog
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7+
8+
## [1.0.0] - 2025-03-31
9+
10+
Initial release.

bip-0374/secp256k1lab/COPYING

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2009-2024 The Bitcoin Core developers
4+
Copyright (c) 2009-2024 Bitcoin Developers
5+
Copyright (c) 2025- The secp256k1lab Developers
6+
7+
Permission is hereby granted, free of charge, to any person obtaining a copy
8+
of this software and associated documentation files (the "Software"), to deal
9+
in the Software without restriction, including without limitation the rights
10+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
copies of the Software, and to permit persons to whom the Software is
12+
furnished to do so, subject to the following conditions:
13+
14+
The above copyright notice and this permission notice shall be included in
15+
all copies or substantial portions of the Software.
16+
17+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23+
THE SOFTWARE.

bip-0374/secp256k1lab/README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
secp256k1lab
2+
============
3+
4+
![Dependencies: None](https://img.shields.io/badge/dependencies-none-success)
5+
6+
An INSECURE implementation of the secp256k1 elliptic curve and related cryptographic schemes written in Python, intended for prototyping, experimentation and education.
7+
8+
Features:
9+
* Low-level secp256k1 field and group arithmetic.
10+
* Schnorr signing/verification and key generation according to [BIP-340](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki).
11+
* ECDH key exchange.
12+
13+
WARNING: The code in this library is slow and trivially vulnerable to side channel attacks.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
[project]
2+
name = "secp256k1lab"
3+
version = "1.0.0"
4+
description = "An INSECURE implementation of the secp256k1 elliptic curve and related cryptographic schemes, intended for prototyping, experimentation and education"
5+
readme = "README.md"
6+
authors = [
7+
{ name = "Pieter Wuille", email = "[email protected]" },
8+
{ name = "Tim Ruffing", email = "[email protected]" },
9+
{ name = "Jonas Nick", email = "[email protected]" },
10+
{ name = "Sebastian Falbesoner", email = "[email protected]" }
11+
]
12+
maintainers = [
13+
{ name = "Tim Ruffing", email = "[email protected]" },
14+
{ name = "Jonas Nick", email = "[email protected]" },
15+
{ name = "Sebastian Falbesoner", email = "[email protected]" }
16+
]
17+
requires-python = ">=3.9"
18+
license = "MIT"
19+
license-files = ["COPYING"]
20+
keywords = ["secp256k1", "elliptic curves", "cryptography", "Bitcoin"]
21+
classifiers = [
22+
"Development Status :: 5 - Production/Stable",
23+
"Intended Audience :: Developers",
24+
"Intended Audience :: Education",
25+
"Intended Audience :: Science/Research",
26+
"License :: OSI Approved :: MIT License",
27+
"Programming Language :: Python",
28+
"Topic :: Security :: Cryptography",
29+
]
30+
dependencies = []
31+
32+
[build-system]
33+
requires = ["hatchling"]
34+
build-backend = "hatchling.build"

0 commit comments

Comments
 (0)