Browse Source

Add dleag and ecdsa otves modules.

anonswap
tecnovert 4 years ago
parent
commit
92cce4287a
No known key found for this signature in database GPG Key ID: 6C1A887B4701EAE3
  1. 9
      .travis/build_windows_wheels.sh
  2. 4
      _cffi_build/build.py
  3. 25
      _cffi_build/secp256k1_dleag.h
  4. 32
      _cffi_build/secp256k1_ecdsaotves.h
  5. 2
      _cffi_build/secp256k1_ed25519.h
  6. 7
      _cffi_build/secp256k1_generator.h
  7. 65
      coincurve/dleag.py
  8. 89
      coincurve/ecdsaotves.py
  9. 35
      coincurve/ed25519.py
  10. 31
      setup.py
  11. 12
      tests/test_dleag.py
  12. 33
      tests/test_ecdsaotves.py

9
.travis/build_windows_wheels.sh

@ -5,14 +5,17 @@ set -e -x
build_dll() {
./autogen.sh
echo "LDFLAGS = -no-undefined" >> Makefile.am
./configure --host=$1 --enable-module-recovery --enable-experimental --enable-module-ecdh --enable-endomorphism --disable-jni
./configure --host=$1 --enable-module-recovery --enable-experimental --enable-module-ecdh --enable-endomorphism --disable-jni --disable-openssl-tests --with-bignum=no --enable-module-ed25519 --enable-module-generator --enable-module-dleag --enable-module-ecdsaotves
make
}
cd ..
git clone https://github.com/bitcoin-core/secp256k1.git
#git clone https://github.com/bitcoin-core/secp256k1.git
#mv secp256k1 64bit
wget -O secp256k1_anonswap.zip https://github.com/tecnovert/secp256k1/archive/anonswap.zip
unzip secp256k1_anonswap.zip
mv secp256k1-anonswap 64bit
mv secp256k1 64bit
cp 64bit 32bit -R
cd 64bit

4
_cffi_build/build.py

@ -27,6 +27,10 @@ modules = [
Source('secp256k1.h', '#include <secp256k1.h>'),
Source('secp256k1_ecdh.h', '#include <secp256k1_ecdh.h>'),
Source('secp256k1_recovery.h', '#include <secp256k1_recovery.h>'),
Source('secp256k1_generator.h', '#include <secp256k1_generator.h>'),
Source('secp256k1_ed25519.h', '#include <secp256k1_ed25519.h>'),
Source('secp256k1_dleag.h', '#include <secp256k1_dleag.h>'),
Source('secp256k1_ecdsaotves.h', '#include <secp256k1_ecdsaotves.h>'),
]
ffi = _mk_ffi(modules, libraries=['secp256k1'])

25
_cffi_build/secp256k1_dleag.h

@ -0,0 +1,25 @@
size_t secp256k1_dleag_size(size_t n_bits);
int secp256k1_dleag_prove(
const secp256k1_context *ctx,
unsigned char *proof_out,
size_t *proof_len, /* Input length of proof_out buffer, output length of proof. */
const unsigned char *key, /* 32 bytes */
size_t n_bits,
const unsigned char *nonce, /* 32 bytes */
const secp256k1_generator *gen_s_a,
const secp256k1_generator *gen_s_b,
const unsigned char *gen_e_a,
const unsigned char *gen_e_b
);
int secp256k1_dleag_verify(
const secp256k1_context *ctx,
const unsigned char *proof,
size_t proof_len,
const secp256k1_generator *gen_s_a,
const secp256k1_generator *gen_s_b,
const unsigned char *gen_e_a,
const unsigned char *gen_e_b
);

32
_cffi_build/secp256k1_ecdsaotves.h

@ -0,0 +1,32 @@
int ecdsaotves_enc_sign(
const secp256k1_context *ctx,
unsigned char *ct_out,
const unsigned char *skS,
const unsigned char *pkE,
const unsigned char *msg32
);
int ecdsaotves_enc_verify(
const secp256k1_context *ctx,
const unsigned char *pkS,
const unsigned char *pkE,
const unsigned char *msg32,
const unsigned char *ct
);
int ecdsaotves_dec_sig(
const secp256k1_context *ctx,
unsigned char *sig_out,
size_t *sig_length,
const unsigned char *skE,
const unsigned char *ct
);
int ecdsaotves_rec_enc_key(
const secp256k1_context *ctx,
unsigned char *key_out,
const unsigned char *pkE,
const unsigned char *ct,
const unsigned char *dersig,
size_t sig_length
);

2
_cffi_build/secp256k1_ed25519.h

@ -0,0 +1,2 @@
extern const unsigned char ed25519_gen[32];
extern const unsigned char ed25519_gen2[32];

7
_cffi_build/secp256k1_generator.h

@ -0,0 +1,7 @@
typedef struct {
unsigned char data[64];
} secp256k1_generator;
extern const secp256k1_generator secp256k1_generator_const_g;
extern const secp256k1_generator secp256k1_generator_const_h;

65
coincurve/dleag.py

@ -0,0 +1,65 @@
from coincurve.context import GLOBAL_CONTEXT
from coincurve.flags import EC_COMPRESSED, EC_UNCOMPRESSED
from ._libsecp256k1 import ffi, lib
def dleag_proof_len(bits=252):
return lib.secp256k1_dleag_size(bits)
def get_nonce():
try:
import secrets
return secrets.token_bytes(32)
except Exception:
from os import urandom
return urandom(32)
def dleag_prove(private_key, context=GLOBAL_CONTEXT):
proof_length = dleag_proof_len()
proof_output = ffi.new('unsigned char[{}]'.format(proof_length))
proof_length_p = ffi.new('size_t *')
proof_length_p[0] = proof_length
# nonce_bytes = ffi.from_buffer(secrets.token_bytes(32))
nonce_bytes = get_nonce()
rv = lib.secp256k1_dleag_prove(
context.ctx,
proof_output,
proof_length_p,
private_key.secret,
252,
nonce_bytes,
ffi.addressof(lib.secp256k1_generator_const_g),
ffi.addressof(lib.secp256k1_generator_const_h),
lib.ed25519_gen,
lib.ed25519_gen2,
)
if rv != 1:
raise ValueError('secp256k1_dleag_prove failed')
# TODO: How to clear memory? Add random module to secp256k1?
# ffi.memmove(nonce_bytes, bytes([0] * 32), 32)
return bytes(ffi.buffer(proof_output, proof_length))
def dleag_verify(proof, context=GLOBAL_CONTEXT):
proof_bytes = ffi.from_buffer(proof)
proof_length = len(proof)
rv = lib.secp256k1_dleag_verify(
context.ctx,
proof_bytes,
proof_length,
ffi.addressof(lib.secp256k1_generator_const_g),
ffi.addressof(lib.secp256k1_generator_const_h),
lib.ed25519_gen,
lib.ed25519_gen2,
)
return True if rv == 1 else False

89
coincurve/ecdsaotves.py

@ -0,0 +1,89 @@
from coincurve.context import GLOBAL_CONTEXT
from coincurve.utils import bytes_to_int, int_to_bytes, sha256
from ._libsecp256k1 import ffi, lib
def ecdsaotves_enc_sign(private_key_sign, public_key_encrypt, msg, context=GLOBAL_CONTEXT):
ct_length = 196
ct_output = ffi.new('unsigned char[{}]'.format(ct_length))
if len(private_key_sign) != 32:
raise ValueError('private_key_sign must be 32 bytes')
if len(public_key_encrypt) != 33:
raise ValueError('public_key_encrypt must be 33 bytes')
if len(msg) != 32:
raise ValueError('msg must be 32 bytes')
rv = lib.ecdsaotves_enc_sign(
context.ctx,
ct_output,
private_key_sign,
public_key_encrypt,
msg,
)
if rv != 1:
raise ValueError('ecdsaotves_enc_sign failed')
return bytes(ffi.buffer(ct_output, ct_length))
def ecdsaotves_enc_verify(public_key_sign, public_key_encrypt, msg, ct, context=GLOBAL_CONTEXT):
if len(public_key_sign) != 33:
raise ValueError('public_key_sign must be 33 bytes')
if len(public_key_encrypt) != 33:
raise ValueError('public_key_encrypt must be 33 bytes')
if len(msg) != 32:
raise ValueError('msg must be 32 bytes')
if len(ct) != 196:
raise ValueError('ciphertext must be 196 bytes')
rv = lib.ecdsaotves_enc_verify(
context.ctx,
public_key_sign,
public_key_encrypt,
msg,
ct,
)
return True if rv == 1 else False
def ecdsaotves_dec_sig(private_key_encrypt, ct, context=GLOBAL_CONTEXT):
if len(private_key_encrypt) != 32:
raise ValueError('private_key_encrypt must be 32 bytes')
if len(ct) != 196:
raise ValueError('ciphertext must be 196 bytes')
output_length = ffi.new('size_t *')
output_length[0] = 100
sig_output = ffi.new('unsigned char[{}]'.format(100))
rv = lib.ecdsaotves_dec_sig(
context.ctx,
sig_output,
output_length,
private_key_encrypt,
ct,
)
if rv != 1:
raise ValueError('ecdsaotves_dec_sig failed')
return bytes(ffi.buffer(sig_output, output_length[0]))
def ecdsaotves_rec_enc_key(public_key_encrypt, ct, sig_der, context=GLOBAL_CONTEXT):
if len(public_key_encrypt) != 33:
raise ValueError('public_key_encrypt must be 33 bytes')
if len(ct) != 196:
raise ValueError('ciphertext must be 196 bytes')
key_output = ffi.new('unsigned char[{}]'.format(32))
sig_length = len(sig_der)
rv = lib.ecdsaotves_rec_enc_key(context.ctx, key_output, public_key_encrypt, ct, sig_der, sig_length)
if rv != 1:
raise ValueError('ecdsaotves_rec_enc_key failed')
return bytes(ffi.buffer(key_output, 32))

35
coincurve/ed25519.py

@ -0,0 +1,35 @@
from asn1crypto.keys import ECDomainParameters, ECPointBitString, ECPrivateKey, PrivateKeyAlgorithm, PrivateKeyInfo
from coincurve.context import GLOBAL_CONTEXT
from coincurve.ecdsa import cdata_to_der, der_to_cdata, deserialize_recoverable, recover, serialize_recoverable
from coincurve.flags import EC_COMPRESSED, EC_UNCOMPRESSED
from coincurve.utils import bytes_to_int, int_to_bytes_padded
from ._libsecp256k1 import ffi, lib
DEFAULT_NONCE = (ffi.NULL, ffi.NULL)
GROUP_ORDER_INT = 2 ** 252 + 27742317777372353535851937790883648493
def get_valid_secret():
try:
import secrets
return int_to_bytes_padded(9 + secrets.randbelow(GROUP_ORDER_INT - 9))
except Exception:
from os import urandom
while True:
secret = urandom(32)
if 9 < bytes_to_int(secret) < GROUP_ORDER_INT:
return secret
class Ed25519PrivateKey:
def __init__(self, secret=None, context=GLOBAL_CONTEXT):
self.context = context
class Ed25519PublicKey:
def __init__(self, data, context=GLOBAL_CONTEXT):
self.context = context

31
setup.py

@ -5,6 +5,7 @@ import platform
import shutil
import subprocess
import tarfile
import zipfile
from distutils import log
from distutils.command.build_clib import build_clib as _build_clib
from distutils.command.build_ext import build_ext as _build_ext
@ -48,6 +49,7 @@ def download_library(command):
if command.dry_run:
return
libdir = absolute('libsecp256k1')
zipdir = absolute('secp256k1-anonswap')
if os.path.exists(os.path.join(libdir, 'autogen.sh')):
# Library already downloaded
return
@ -55,7 +57,16 @@ def download_library(command):
command.announce('downloading libsecp256k1 source code', level=log.INFO)
try:
import requests
zip_url = 'https://github.com/tecnovert/secp256k1/archive/anonswap.zip'
r = requests.get(zip_url, stream=True)
status_code = r.status_code
if status_code == 200:
content = BytesIO(r.raw.read())
content.seek(0)
with zipfile.ZipFile(content) as zip_ref:
zip_ref.extractall(absolute())
shutil.move(zipdir, libdir)
"""
r = requests.get(LIB_TARBALL_URL, stream=True)
status_code = r.status_code
if status_code == 200:
@ -67,6 +78,7 @@ def download_library(command):
shutil.move(dirname, libdir)
else:
raise SystemExit('Unable to download secp256k1 library: HTTP-Status: %d', status_code)
"""
except requests.exceptions.RequestException as e:
raise SystemExit('Unable to download secp256k1 library: %s', str(e))
@ -127,9 +139,9 @@ class build_clib(_build_clib):
return build_flags('libsecp256k1', 'l', os.path.abspath(self.build_temp))
def run(self):
if has_system_lib():
log.info('Using system library')
return
#if has_system_lib():
# log.info('Using system library')
# return
build_temp = os.path.abspath(self.build_temp)
@ -175,13 +187,18 @@ class build_clib(_build_clib):
'--disable-dependency-tracking',
'--with-pic',
'--enable-module-recovery',
'--disable-jni',
'--prefix',
os.path.abspath(self.build_clib),
'--enable-experimental',
'--enable-module-ecdh',
'--enable-benchmark=no',
# '--enable-endomorphism',
#'--enable-benchmark=no',
'--enable-benchmark=yes',
'--enable-module-ed25519',
'--enable-module-generator',
'--enable-module-dleag',
'--enable-module-ecdsaotves',
'--with-bignum=no',
'--with-valgrind=no'
]
log.debug('Running configure: {}'.format(' '.join(cmd)))

12
tests/test_dleag.py

@ -0,0 +1,12 @@
from coincurve.dleag import dleag_prove, dleag_verify
from coincurve.ed25519 import get_valid_secret
from coincurve.keys import PrivateKey, PublicKey
class TestDLEAG:
def test_dleag(self):
secret = get_valid_secret()
private_key = PrivateKey(secret)
proof = dleag_prove(private_key)
assert True == dleag_verify(proof)

33
tests/test_ecdsaotves.py

@ -0,0 +1,33 @@
import sys
from coincurve.ecdsaotves import ecdsaotves_enc_sign, ecdsaotves_enc_verify, ecdsaotves_dec_sig, ecdsaotves_rec_enc_key
from coincurve.keys import PrivateKey, PublicKey
from coincurve.utils import get_valid_secret, sha256
class TestECDSAOTVES:
def test_ecdsaotves(self):
secret_sign = get_valid_secret()
secret_encrypt = get_valid_secret()
pk_sign = PublicKey.from_secret(secret_sign)
pk_encrypt = PublicKey.from_secret(secret_encrypt)
pk_sb = pk_sign.format()
pk_eb = pk_encrypt.format()
message = 'otves message'
if sys.version_info[0] > 2:
message_hash = sha256(bytes(message, 'utf-8'))
else:
message_hash = sha256(message)
ct = ecdsaotves_enc_sign(secret_sign, pk_eb, message_hash)
assert ecdsaotves_enc_verify(pk_sb, pk_eb, message_hash, ct)
sig = ecdsaotves_dec_sig(secret_encrypt, ct)
assert pk_sign.verify(sig, message_hash, hasher=None)
secret_rec = ecdsaotves_rec_enc_key(pk_eb, ct, sig)
assert secret_rec == secret_encrypt
Loading…
Cancel
Save