ofek
7 years ago
14 changed files with 120 additions and 1751 deletions
@ -1,2 +1,2 @@ |
|||
from coincurve.context import GLOBAL_CONTEXT |
|||
from coincurve.context import GLOBAL_CONTEXT, Context |
|||
from coincurve.keys import PrivateKey, PublicKey |
|||
|
File diff suppressed because it is too large
@ -0,0 +1,21 @@ |
|||
PRIVATE_KEY_BYTES = b'\xc2\x8a\x9f\x80s\x8fw\rRx\x03\xa5f\xcfo\xc3\xed\xf6\xce\xa5\x86\xc4\xfcJR#\xa5\xady~\x1a\xc3' |
|||
PRIVATE_KEY_DER = (b"0\x81\x84\x02\x01\x000\x10\x06\x07*\x86H\xce=\x02\x01\x06" |
|||
b"\x05+\x81\x04\x00\n\x04m0k\x02\x01\x01\x04 \xc2\x8a\x9f" |
|||
b"\x80s\x8fw\rRx\x03\xa5f\xcfo\xc3\xed\xf6\xce\xa5\x86\xc4" |
|||
b"\xfcJR#\xa5\xady~\x1a\xc3\xa1D\x03B\x00\x04=\\(u\xc9\xbd" |
|||
b"\x11hu\xa7\x1a]\xb6L\xff\xcb\x139k\x16=\x03\x9b\x1d\x93'" |
|||
b"\x82H\x91\x80C4v\xa45**\xdd\x00\xeb\xb0\xd5\xc9LQ[r\xeb" |
|||
b"\x10\xf1\xfd\x8f?\x03\xb4/J+%[\xfc\x9a\xa9\xe3") |
|||
PRIVATE_KEY_HEX = 'c28a9f80738f770d527803a566cf6fc3edf6cea586c4fc4a5223a5ad797e1ac3' |
|||
PRIVATE_KEY_NUM = 87993618360805341115891506172036624893404292644470266399436498750715784469187 |
|||
PRIVATE_KEY_PEM = (b'-----BEGIN PRIVATE KEY-----\n' |
|||
b'MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQgwoqfgHOPdw1SeAOlZs9v\n' |
|||
b'w+32zqWGxPxKUiOlrXl+GsOhRANCAAQ9XCh1yb0RaHWnGl22TP/LEzlrFj0Dmx2T\n' |
|||
b'J4JIkYBDNHakNSoq3QDrsNXJTFFbcusQ8f2PPwO0L0orJVv8mqnj\n' |
|||
b'-----END PRIVATE KEY-----\n') |
|||
PUBLIC_KEY_COMPRESSED = b"\x03=\\(u\xc9\xbd\x11hu\xa7\x1a]\xb6L\xff\xcb\x139k\x16=\x03\x9b\x1d\x93'\x82H\x91\x80C4" |
|||
PUBLIC_KEY_UNCOMPRESSED = (b"\x04=\\(u\xc9\xbd\x11hu\xa7\x1a]\xb6L\xff\xcb\x139k\x16=\x03" |
|||
b"\x9b\x1d\x93'\x82H\x91\x80C4v\xa45**\xdd\x00\xeb\xb0\xd5\xc9" |
|||
b"LQ[r\xeb\x10\xf1\xfd\x8f?\x03\xb4/J+%[\xfc\x9a\xa9\xe3") |
|||
PUBLIC_KEY_X = 27753912938952041417634381842191885283234814940840273460372041880794577257268 |
|||
PUBLIC_KEY_Y = 53663045980837260634637807506183816949039230809110041985901491152185762425315 |
@ -1,64 +0,0 @@ |
|||
import os |
|||
import json |
|||
import pytest |
|||
import coincurve |
|||
|
|||
HERE = os.path.dirname(os.path.abspath(__file__)) |
|||
DATA = os.path.join(HERE, 'data') |
|||
|
|||
from cffi import FFI |
|||
|
|||
ffi = FFI() |
|||
ffi.cdef('static int nonce_function_rand(unsigned char *nonce32,' |
|||
'const unsigned char *msg32,const unsigned char *key32,' |
|||
'const unsigned char *algo16,void *data,unsigned int attempt);') |
|||
|
|||
#The most elementary conceivable nonce function, acting |
|||
#as a passthrough: user provides random data which must be |
|||
#a valid scalar nonce. This is not ideal, |
|||
#since libsecp256k1 expects the nonce output from |
|||
#this function to result in a valid sig (s!=0), and will |
|||
#increment the counter ("attempt") and try again if it fails; |
|||
#since we don't increment the counter here, that will not succeed. |
|||
#Of course the likelihood of such an error is infinitesimal. |
|||
#TLDR this is not intended to be used in real life; use |
|||
#deterministic signatures. |
|||
ffi.set_source("_noncefunc", |
|||
""" |
|||
static int nonce_function_rand(unsigned char *nonce32, |
|||
const unsigned char *msg32, |
|||
const unsigned char *key32, |
|||
const unsigned char *algo16, |
|||
void *data, |
|||
unsigned int attempt) |
|||
{ |
|||
memcpy(nonce32,data,32); |
|||
return 1; |
|||
} |
|||
""") |
|||
|
|||
ffi.compile() |
|||
|
|||
import _noncefunc |
|||
from _noncefunc import ffi |
|||
|
|||
|
|||
def test_ecdsa_with_custom_nonce(): |
|||
with open(os.path.join(DATA, 'ecdsa_custom_nonce_sig.json')) as f: |
|||
data = f.read() |
|||
vec = json.loads(data)['vectors'] |
|||
inst = coincurve.PrivateKey() |
|||
for item in vec: |
|||
seckey = bytes(bytearray.fromhex(item['privkey'])) |
|||
msg32 = bytes(bytearray.fromhex(item['msg'])) |
|||
sig = bytes(bytearray.fromhex(item['sig'])) |
|||
randnonce = bytes(bytearray.fromhex(item['nonce'])) |
|||
inst.set_raw_privkey(seckey) |
|||
nf = ffi.addressof(_noncefunc.lib, "nonce_function_rand") |
|||
ndata = ffi.new("char [32]", randnonce) |
|||
sig_raw = inst.ecdsa_sign(msg32, raw=True, custom_nonce=(nf, ndata)) |
|||
sig_check = inst.ecdsa_serialize(sig_raw) |
|||
assert sig_check == sig |
|||
assert inst.ecdsa_serialize(inst.ecdsa_deserialize(sig_check)) == sig_check |
|||
assert inst.pubkey.ecdsa_verify(msg32, sig_raw, raw=True) |
|||
|
@ -1,22 +0,0 @@ |
|||
import pytest |
|||
|
|||
import coincurve |
|||
|
|||
|
|||
def test_ecdh(): |
|||
if not coincurve.HAS_ECDH: |
|||
pytest.skip('secp256k1_ecdh not enabled, skipping') |
|||
return |
|||
|
|||
pubkey = coincurve.PrivateKey().pubkey |
|||
|
|||
p = coincurve.PublicKey(pubkey.public_key) |
|||
with pytest.raises(Exception): |
|||
# Bad scalar length. |
|||
p.ecdh(b'') |
|||
with pytest.raises(Exception): |
|||
# Bad scalar type. |
|||
p.ecdh([]) |
|||
|
|||
res = p.ecdh(b'0' * 32) |
|||
assert type(res) == bytes |
@ -1,102 +0,0 @@ |
|||
import os |
|||
import json |
|||
import pytest |
|||
from io import StringIO |
|||
|
|||
import coincurve |
|||
|
|||
HERE = os.path.dirname(os.path.abspath(__file__)) |
|||
DATA = os.path.join(HERE, 'data') |
|||
|
|||
|
|||
def test_ecdsa(): |
|||
with open(os.path.join(DATA, 'ecdsa_sig.json')) as f: |
|||
data = f.read() |
|||
vec = json.loads(data)['vectors'] |
|||
|
|||
inst = coincurve.PrivateKey() |
|||
|
|||
for item in vec: |
|||
seckey = bytes(bytearray.fromhex(item['privkey'])) |
|||
msg32 = bytes(bytearray.fromhex(item['msg'])) |
|||
sig = bytes(bytearray.fromhex(item['sig'])[:-1]) |
|||
|
|||
inst.set_raw_privkey(seckey) |
|||
|
|||
sig_raw = inst.ecdsa_sign(msg32, raw=True) |
|||
sig_check = inst.ecdsa_serialize(sig_raw) |
|||
assert sig_check == sig |
|||
assert inst.ecdsa_serialize(inst.ecdsa_deserialize(sig_check)) == sig_check |
|||
|
|||
assert inst.pubkey.ecdsa_verify(msg32, sig_raw, raw=True) |
|||
|
|||
|
|||
def test_ecdsa_compact(): |
|||
key = coincurve.PrivateKey() |
|||
raw_sig = key.ecdsa_sign(b'test') |
|||
assert key.pubkey.ecdsa_verify(b'test', raw_sig) |
|||
|
|||
compact = key.ecdsa_serialize_compact(raw_sig) |
|||
assert len(compact) == 64 |
|||
|
|||
sig_raw = key.ecdsa_deserialize_compact(compact) |
|||
assert key.ecdsa_serialize_compact(sig_raw) == compact |
|||
assert key.pubkey.ecdsa_verify(b'test', sig_raw) |
|||
|
|||
|
|||
def test_ecdsa_normalize(): |
|||
key = coincurve.PrivateKey() |
|||
raw_sig = key.ecdsa_sign(b'hi') |
|||
|
|||
had_to_normalize, normsig = key.ecdsa_signature_normalize(raw_sig) |
|||
assert had_to_normalize == False |
|||
assert key.ecdsa_serialize(normsig) == key.ecdsa_serialize(raw_sig) |
|||
assert key.ecdsa_serialize_compact(normsig) == \ |
|||
key.ecdsa_serialize_compact(raw_sig) |
|||
|
|||
had_to_normalize, normsig = key.ecdsa_signature_normalize( |
|||
raw_sig, check_only=True) |
|||
assert had_to_normalize == False |
|||
assert normsig == None |
|||
|
|||
sig = b'\xAA' + (b'\xFF' * 31) + b'\xAA' + (b'\xFF' * 31) |
|||
raw_sig = key.ecdsa_deserialize_compact(sig) |
|||
normalized, normsig = key.ecdsa_signature_normalize(raw_sig) |
|||
assert normalized == True |
|||
assert key.ecdsa_serialize(normsig) != key.ecdsa_serialize(raw_sig) |
|||
normalized, normsig = key.ecdsa_signature_normalize(raw_sig, True) |
|||
assert normalized == True |
|||
assert normsig == None |
|||
|
|||
|
|||
def test_ecdsa_recover(): |
|||
if not coincurve.HAS_RECOVERABLE: |
|||
pytest.skip('secp256k1_recovery not enabled, skipping') |
|||
return |
|||
|
|||
class MyECDSA(coincurve.Base, coincurve.ECDSA): |
|||
def __init__(self): |
|||
coincurve.Base.__init__(self, ctx=None, flags=coincurve.ALL_FLAGS) |
|||
|
|||
privkey = coincurve.PrivateKey() |
|||
unrelated = MyECDSA() |
|||
|
|||
# Create a signature that allows recovering the public key. |
|||
recsig = privkey.ecdsa_sign_recoverable(b'hello') |
|||
# Recover the public key. |
|||
pubkey = unrelated.ecdsa_recover(b'hello', recsig) |
|||
# Check that the recovered public key matches the one used |
|||
# in privkey.pubkey. |
|||
pubser = coincurve.PublicKey(pubkey).serialize() |
|||
assert privkey.pubkey.serialize() == pubser |
|||
|
|||
# Check that after serializing and deserializing recsig |
|||
# we still recover the same public key. |
|||
recsig_ser = unrelated.ecdsa_recoverable_serialize(recsig) |
|||
recsig2 = unrelated.ecdsa_recoverable_deserialize(*recsig_ser) |
|||
pubkey2 = unrelated.ecdsa_recover(b'hello', recsig2) |
|||
pubser2 = coincurve.PublicKey(pubkey2).serialize() |
|||
assert pubser == pubser2 |
|||
|
|||
raw_sig = unrelated.ecdsa_recoverable_convert(recsig2) |
|||
unrelated.ecdsa_deserialize(unrelated.ecdsa_serialize(raw_sig)) |
@ -1,140 +0,0 @@ |
|||
import pytest |
|||
import hashlib |
|||
import coincurve |
|||
|
|||
|
|||
def test_privkey(): |
|||
with pytest.raises(TypeError): |
|||
key = 'abc' |
|||
coincurve.PrivateKey(key) |
|||
|
|||
with pytest.raises(TypeError): |
|||
key = bytearray.fromhex('a' * 32) # This will result in 16 bytes. |
|||
coincurve.PrivateKey(bytes(key)) |
|||
|
|||
with pytest.raises(Exception): |
|||
coincurve.PrivateKey(bytes(bytearray.fromhex('0' * 64))) |
|||
|
|||
with pytest.raises(Exception): |
|||
coincurve.PrivateKey(bytes(bytearray.fromhex('F' * 64))) |
|||
|
|||
with pytest.raises(Exception): |
|||
# This is a good raw key, but here it's being passed as serialized. |
|||
coincurve.PrivateKey(b'1' * 32, raw=False) |
|||
|
|||
# "good" key, should be fine. |
|||
assert coincurve.PrivateKey(b'1' * 32) |
|||
|
|||
|
|||
def test_publickey(): |
|||
with pytest.raises(Exception): |
|||
# Must be bytes. |
|||
|
|||
# In Python 2 this will not raise a TypeError |
|||
# since bytes is an alias to str, instead it will fail |
|||
# during deserialization. |
|||
coincurve.PublicKey('abc', raw=True) |
|||
with pytest.raises(Exception): |
|||
coincurve.PublicKey([], raw=True) |
|||
|
|||
with pytest.raises(Exception): |
|||
# Invalid size. |
|||
coincurve.PublicKey(b'abc', raw=True) |
|||
|
|||
with pytest.raises(Exception): |
|||
# Invalid public key. |
|||
coincurve.PublicKey(b'a' * 33, raw=True) |
|||
|
|||
# Invalid usage: passing a raw public key but not specifying raw=True. |
|||
with pytest.raises(TypeError): |
|||
coincurve.PublicKey(b'a' * 33) |
|||
|
|||
# No public key. |
|||
assert coincurve.PublicKey() |
|||
|
|||
pub1 = coincurve.PrivateKey().pubkey.public_key |
|||
new = coincurve.PublicKey() |
|||
with pytest.raises(AssertionError): |
|||
# Trying to combine with something that is not a public key. |
|||
new.combine([pub1, coincurve.ffi.NULL]) |
|||
|
|||
new = coincurve.PublicKey() |
|||
with pytest.raises(AssertionError): |
|||
# Nothing to combine. |
|||
new.combine([]) |
|||
|
|||
|
|||
def test_ecdsa(): |
|||
rawkey = (b'\xc9\xa9)Z\xf8Er\x97\x8b\xa23\x1f\xf7\xb6\x82qQ\xdc9\xc1' |
|||
b'\x1d\xac6\xfd\xeb\x11\x05\xb1\xdf\x86\xb3\xe6') |
|||
priv = coincurve.PrivateKey(rawkey) |
|||
with pytest.raises(Exception): |
|||
# Bad digest function (doesn't produce 256 bits). |
|||
priv.ecdsa_sign(b'hi', digest=hashlib.sha1) |
|||
|
|||
raw_sig = priv.ecdsa_sign(b'hi') |
|||
assert priv.pubkey.ecdsa_verify(b'hi', raw_sig) |
|||
|
|||
with pytest.raises(AssertionError): |
|||
sig = priv.ecdsa_serialize(raw_sig)[:-1] |
|||
priv.ecdsa_deserialize(sig) |
|||
|
|||
sig = priv.ecdsa_serialize(raw_sig) |
|||
sig = sig[:-1] + bytes(sig[0:1]) # Assuming sig[0] != sig[-1]. |
|||
invalid_sig = priv.ecdsa_deserialize(sig) |
|||
assert not priv.pubkey.ecdsa_verify(b'hi', invalid_sig) |
|||
|
|||
|
|||
def test_ecdsa_compact(): |
|||
key = coincurve.PrivateKey() |
|||
|
|||
raw_sig = key.ecdsa_sign(b'hi') |
|||
with pytest.raises(TypeError): |
|||
# Should pass a compact serialization. |
|||
key.ecdsa_deserialize_compact(raw_sig) |
|||
|
|||
ser = key.ecdsa_serialize(raw_sig) |
|||
with pytest.raises(Exception): |
|||
# A serialization that is not compact has more than 64 bytes. |
|||
key.ecdsa_deserialize_compact(ser) |
|||
|
|||
|
|||
def test_ecdsa_recoverable(): |
|||
if not coincurve.HAS_RECOVERABLE: |
|||
pytest.skip('secp256k1_recovery not enabled, skipping') |
|||
return |
|||
|
|||
key = '32a8935ffdb984a498b0f7ac8943e0d2ac084e81c809595fd19fde41522f1837' |
|||
priv = coincurve.PrivateKey(bytes(bytearray.fromhex(key))) |
|||
sig = priv.ecdsa_sign_recoverable(b'hi') |
|||
sig_ser, rec_id = priv.ecdsa_recoverable_serialize(sig) |
|||
assert rec_id == 1 |
|||
|
|||
with pytest.raises(Exception): |
|||
# Invalid rec_id (must be between 0 and 3) |
|||
priv.ecdsa_recoverable_deserialize(sig_ser, -1) |
|||
|
|||
# Deserialize using a rec_id that does not match. |
|||
sig = priv.ecdsa_recoverable_deserialize(sig_ser, 2) |
|||
with pytest.raises(Exception): |
|||
# Now try to recover the public key. |
|||
priv.ecdsa_recover(b'hi', sig) |
|||
|
|||
# Invalid size. |
|||
with pytest.raises(Exception): |
|||
priv.ecdsa_recoverable_deserialize(b'hello', 0) |
|||
|
|||
|
|||
def test_tweak(): |
|||
key = coincurve.PrivateKey() |
|||
|
|||
# Tweak out of range |
|||
scalar = b'\xFF' * 32 |
|||
with pytest.raises(Exception): |
|||
key.tweak_mul(scalar) |
|||
with pytest.raises(Exception): |
|||
key.tweak_add(scalar) |
|||
with pytest.raises(Exception): |
|||
key.pubkey.tweak_mul(scalar) |
|||
with pytest.raises(Exception): |
|||
key.pubkey.tweak_add(scalar) |
@ -1,63 +0,0 @@ |
|||
import pytest |
|||
import coincurve |
|||
|
|||
|
|||
def test_values(): |
|||
assert coincurve.FLAG_VERIFY == ( |
|||
coincurve.lib.SECP256K1_FLAGS_TYPE_CONTEXT | |
|||
coincurve.lib.SECP256K1_FLAGS_BIT_CONTEXT_VERIFY) |
|||
assert coincurve.FLAG_VERIFY == 257 |
|||
assert coincurve.FLAG_SIGN == ( |
|||
coincurve.lib.SECP256K1_FLAGS_TYPE_CONTEXT | |
|||
coincurve.lib.SECP256K1_FLAGS_BIT_CONTEXT_SIGN) |
|||
assert coincurve.FLAG_SIGN == 513 |
|||
assert coincurve.ALL_FLAGS == coincurve.FLAG_SIGN | coincurve.FLAG_VERIFY |
|||
|
|||
|
|||
def test_privkey(): |
|||
with pytest.raises(AssertionError): |
|||
coincurve.PrivateKey(flags=coincurve.FLAG_VERIFY) |
|||
with pytest.raises(AssertionError): |
|||
coincurve.PrivateKey(flags=0) |
|||
|
|||
privkey = coincurve.PrivateKey(flags=coincurve.FLAG_SIGN) |
|||
sig = privkey.ecdsa_sign(b'hi') |
|||
with pytest.raises(Exception): |
|||
# FLAG_SIGN was not specified. |
|||
privkey.pubkey.ecdsa_verify(b'hi', sig) |
|||
|
|||
assert privkey.flags == privkey.pubkey.flags |
|||
|
|||
privkey = coincurve.PrivateKey() |
|||
sig = privkey.ecdsa_sign(b'hi') |
|||
assert privkey.pubkey.ecdsa_verify(b'hi', sig) |
|||
|
|||
|
|||
def test_pubkey(): |
|||
privkey = coincurve.PrivateKey() |
|||
sig = privkey.ecdsa_sign(b'hello') |
|||
pubkeyser = privkey.pubkey.serialize() |
|||
|
|||
pubkey = coincurve.PublicKey(pubkeyser, raw=True, flags=coincurve.NO_FLAGS) |
|||
with pytest.raises(Exception): |
|||
# FLAG_SIGN was not specified. |
|||
pubkey.ecdsa_verify(b'hello', sig) |
|||
|
|||
pubkey = coincurve.PublicKey(pubkeyser, raw=True) |
|||
assert pubkey.ecdsa_verify(b'hello', sig) |
|||
|
|||
|
|||
def test_recoverable(): |
|||
if not coincurve.HAS_RECOVERABLE: |
|||
pytest.skip('secp256k1_recovery not enabled, skipping') |
|||
return |
|||
|
|||
privkey = coincurve.PrivateKey(flags=coincurve.FLAG_SIGN) |
|||
x = privkey.ecdsa_sign_recoverable(b'hi') |
|||
with pytest.raises(Exception): |
|||
# All flags required. |
|||
privkey.ecdsa_recover(b'hi', x) |
|||
|
|||
privkey = coincurve.PrivateKey() |
|||
x = privkey.ecdsa_sign_recoverable(b'hi') |
|||
privkey.ecdsa_recover(b'hi', x) |
@ -1,46 +0,0 @@ |
|||
import os |
|||
import json |
|||
from io import StringIO |
|||
|
|||
import coincurve |
|||
|
|||
HERE = os.path.dirname(os.path.abspath(__file__)) |
|||
DATA = os.path.join(HERE, 'data') |
|||
|
|||
|
|||
def test_pubkey_from_privkey(): |
|||
with open(os.path.join(DATA, 'pubkey.json')) as f: |
|||
data = f.read() |
|||
vec = json.loads(data)['vectors'] |
|||
|
|||
inst = coincurve.PrivateKey() |
|||
|
|||
for item in vec: |
|||
seckey = bytes(bytearray.fromhex(item['seckey'])) |
|||
pubkey_uncp = bytes(bytearray.fromhex(item['pubkey'])) |
|||
pubkey_comp = bytes(bytearray.fromhex(item['compressed'])) |
|||
|
|||
inst.set_raw_privkey(seckey) |
|||
|
|||
assert inst.pubkey.serialize(compressed=False) == pubkey_uncp |
|||
assert inst.pubkey.serialize(compressed=True) == pubkey_comp |
|||
|
|||
assert inst.deserialize(inst.serialize()) == seckey |
|||
|
|||
|
|||
def test_pubkey_combine(): |
|||
k1 = coincurve.PrivateKey() |
|||
k2 = coincurve.PrivateKey() |
|||
|
|||
pub1 = k1.pubkey.public_key |
|||
pub2 = k2.pubkey.public_key |
|||
new = coincurve.PublicKey() |
|||
assert new.public_key is None |
|||
res = new.combine([pub1, pub2]) |
|||
assert new.public_key == res |
|||
|
|||
new = coincurve.PublicKey() |
|||
assert new.public_key is None |
|||
res = new.combine([pub1]) |
|||
assert new.public_key == res |
|||
assert new.serialize() == k1.pubkey.serialize() |
@ -1,44 +0,0 @@ |
|||
import pytest |
|||
import coincurve |
|||
|
|||
|
|||
def test_pubkey_tweak(): |
|||
inst = coincurve.PrivateKey() |
|||
pub = inst.pubkey |
|||
|
|||
scalar = [b'\x01' * 32] |
|||
with pytest.raises(TypeError): |
|||
pub.tweak_add(scalar) |
|||
with pytest.raises(TypeError): |
|||
pub.tweak_mul(scalar) |
|||
|
|||
scalar = b'\x01' * 31 |
|||
with pytest.raises(TypeError): |
|||
pub.tweak_add(scalar) |
|||
with pytest.raises(TypeError): |
|||
pub.tweak_mul(scalar) |
|||
|
|||
scalar = scalar + b'\x01' |
|||
res = pub.tweak_add(scalar) |
|||
assert isinstance(res, coincurve.PublicKey) |
|||
assert res.serialize() != pub.serialize() |
|||
|
|||
|
|||
def test_privkey_tweak(): |
|||
key = coincurve.PrivateKey() |
|||
|
|||
scalar = [b'\x01' * 32] |
|||
with pytest.raises(TypeError): |
|||
key.tweak_add(scalar) |
|||
with pytest.raises(TypeError): |
|||
key.tweak_mul(scalar) |
|||
|
|||
scalar = b'\x01' * 31 |
|||
with pytest.raises(TypeError): |
|||
key.tweak_add(scalar) |
|||
with pytest.raises(TypeError): |
|||
key.tweak_mul(scalar) |
|||
|
|||
scalar = scalar + b'\x01' |
|||
res = key.tweak_add(scalar) |
|||
assert isinstance(res, bytes) and len(res) == 32 |
Loading…
Reference in new issue