Esempio n. 1
0
    def sec(self, compressed=True):
        """returns the binary version of the SEC format"""
        if compressed:
            if not self.csec:
                serialized = ffi.new("unsigned char [33]")
                output_len = ffi.new("size_t *", 33)

                if not lib.secp256k1_ec_pubkey_serialize(
                        GLOBAL_CTX,
                        serialized,
                        output_len,
                        self.c,
                        lib.SECP256K1_EC_COMPRESSED,
                ):
                    raise RuntimeError("libsecp256k1 serialize error")
                self.csec = bytes(ffi.buffer(serialized, 33))
            return self.csec
        else:
            if not self.usec:
                serialized = ffi.new("unsigned char [65]")
                output_len = ffi.new("size_t *", 65)

                if not lib.secp256k1_ec_pubkey_serialize(
                        GLOBAL_CTX,
                        serialized,
                        output_len,
                        self.c,
                        lib.SECP256K1_EC_UNCOMPRESSED,
                ):
                    raise RuntimeError("libsecp256k1 serialize error")
                self.usec = bytes(ffi.buffer(serialized, 65))
            return self.usec
Esempio n. 2
0
 def der(self):
     if not self.der_cache:
         der = ffi.new("unsigned char[72]")
         der_length = ffi.new("size_t *", 72)
         if not lib.secp256k1_ecdsa_signature_serialize_der(
                 GLOBAL_CTX, der, der_length, self.c):
             raise RuntimeError("libsecp256k1 der serialize error")
         self.der_cache = bytes(ffi.buffer(der, der_length[0]))
     return self.der_cache
Esempio n. 3
0
 def bip340(self):
     # returns the binary version of BIP340 pubkey
     xonly_key = ffi.new("secp256k1_xonly_pubkey *")
     if not lib.secp256k1_xonly_pubkey_from_pubkey(GLOBAL_CTX, xonly_key,
                                                   ffi.NULL, self.c):
         raise RuntimeError("libsecp256k1 xonly pubkey error")
     output32 = ffi.new("unsigned char [32]")
     if not lib.secp256k1_xonly_pubkey_serialize(GLOBAL_CTX, output32,
                                                 xonly_key):
         raise RuntimeError("libsecp256k1 xonly serialize error")
     return bytes(ffi.buffer(output32, 32))
Esempio n. 4
0
 def verify_schnorr(self, msg, sig):
     xonly_key = ffi.new("secp256k1_xonly_pubkey *")
     if not lib.secp256k1_xonly_pubkey_from_pubkey(GLOBAL_CTX, xonly_key,
                                                   ffi.NULL, self.c):
         raise RuntimeError("libsecp256k1 xonly pubkey error")
     return lib.secp256k1_schnorrsig_verify(GLOBAL_CTX, sig.raw, msg,
                                            len(msg), xonly_key)
Esempio n. 5
0
 def __rmul__(self, coefficient):
     coef = coefficient % N
     new_key = ffi.new("secp256k1_pubkey *")
     s = self.sec(compressed=False)
     if not lib.secp256k1_ec_pubkey_parse(GLOBAL_CTX, new_key, s, len(s)):
         raise RuntimeError("libsecp256k1 parse error")
     if not lib.secp256k1_ec_pubkey_tweak_mul(GLOBAL_CTX, new_key,
                                              int_to_big_endian(coef, 32)):
         raise RuntimeError("libsecp256k1 multiplication error")
     serialized = ffi.new("unsigned char [65]")
     output_len = ffi.new("size_t *", 65)
     if not lib.secp256k1_ec_pubkey_serialize(
             GLOBAL_CTX, serialized, output_len, new_key,
             lib.SECP256K1_EC_UNCOMPRESSED):
         raise RuntimeError("libsecp256k1 serialization error")
     return self.__class__(usec=bytes(serialized))
Esempio n. 6
0
 def __add__(self, scalar):
     """Multiplies scalar by generator, adds result to current point"""
     coef = scalar % N
     new_key = ffi.new("secp256k1_pubkey *")
     s = self.sec(compressed=False)
     if not lib.secp256k1_ec_pubkey_parse(GLOBAL_CTX, new_key, s, len(s)):
         raise RuntimeError("libsecp256k1 parse error")
     if not lib.secp256k1_ec_pubkey_tweak_add(GLOBAL_CTX, new_key,
                                              int_to_big_endian(coef, 32)):
         raise RuntimeError("libsecp256k1 add error")
     serialized = ffi.new("unsigned char [65]")
     output_len = ffi.new("size_t *", 65)
     if not lib.secp256k1_ec_pubkey_serialize(
             GLOBAL_CTX, serialized, output_len, new_key,
             lib.SECP256K1_EC_UNCOMPRESSED):
         raise RuntimeError("libsecp256k1 serialize error")
     return self.__class__(usec=bytes(serialized))
Esempio n. 7
0
 def sign_schnorr(self, msg, aux):
     if len(msg) != 32:
         raise ValueError("msg needs to be 32 bytes")
     if len(aux) != 32:
         raise ValueError("aux needs to be 32 bytes")
     # per libsecp256k1 documentation, this helps against side-channel attacks
     if not lib.secp256k1_context_randomize(
             GLOBAL_CTX,
             secrets.token_bytes(32),
     ):
         raise RuntimeError("libsecp256k1 context randomization error")
     keypair = ffi.new("secp256k1_keypair *")
     if not lib.secp256k1_keypair_create(
             GLOBAL_CTX, keypair, int_to_big_endian(self.secret, 32)):
         raise RuntimeError("libsecp256k1 keypair creation problem")
     raw_sig = ffi.new("unsigned char [64]")
     if not lib.secp256k1_schnorrsig_sign(GLOBAL_CTX, raw_sig, msg, keypair,
                                          aux):
         raise RuntimeError("libsecp256k1 schnorr signing problem")
     return SchnorrSignature(bytes(ffi.buffer(raw_sig, 64)))
Esempio n. 8
0
 def __init__(self, der=None, c=None):
     if der:
         self.der_cache = der
         self.c = ffi.new("secp256k1_ecdsa_signature *")
         if not lib.secp256k1_ecdsa_signature_parse_der(
                 GLOBAL_CTX, self.c, der, len(der)):
             raise RuntimeError(f"badly formatted signature {der.hex()}")
     elif c:
         self.c = c
         self.der_cache = None
     else:
         raise RuntimeError("need der or c object")
Esempio n. 9
0
def tagged_hash(tag, msg):
    result = ffi.new("unsigned char [32]")
    tag_length = len(tag)
    msg_length = len(msg)
    if not lib.secp256k1_tagged_sha256(
            GLOBAL_CTX,
            result,
            tag,
            tag_length,
            msg,
            msg_length,
    ):
        raise RuntimeError("libsecp256k1 tagged hash problem")
    return bytes(ffi.buffer(result, 32))
Esempio n. 10
0
 def __init__(self, raw):
     self.raw = raw
     if len(raw) != 64:
         raise ValueError("signature should be 64 bytes")
     # check that the sig's R is valid
     if big_endian_to_int(raw[:32]) == 0:
         raise AssertionError("R should not be zero")
     xonly_key = ffi.new("secp256k1_xonly_pubkey *")
     if not lib.secp256k1_xonly_pubkey_parse(GLOBAL_CTX, xonly_key,
                                             raw[:32]):
         raise ValueError(f"libsecp256k1 invalid R {raw[:32].hex()}")
     s = big_endian_to_int(raw[32:])
     if s >= N:
         raise ValueError(f"{s:x} is greater than or equal to {N:x}")
Esempio n. 11
0
 def combine(cls, points):
     c_pubkeys = []
     for point in points:
         new_key = ffi.new("secp256k1_pubkey *")
         s = point.sec(compressed=False)
         if not lib.secp256k1_ec_pubkey_parse(GLOBAL_CTX, new_key, s,
                                              len(s)):
             raise RuntimeError("libsecp256k1 parse error")
         c_pubkeys.append(new_key)
     sum_pub_key = ffi.new("secp256k1_pubkey *")
     if not lib.secp256k1_ec_pubkey_combine(GLOBAL_CTX, sum_pub_key,
                                            c_pubkeys, len(c_pubkeys)):
         raise RuntimeError("libsecp256k1 combine error")
     serialized = ffi.new("unsigned char [65]")
     output_len = ffi.new("size_t *", 65)
     if not lib.secp256k1_ec_pubkey_serialize(
             GLOBAL_CTX,
             serialized,
             output_len,
             sum_pub_key,
             lib.SECP256K1_EC_UNCOMPRESSED,
     ):
         raise RuntimeError("libsecp256k1 serialization error")
     return cls(usec=bytes(serialized))
Esempio n. 12
0
 def sign(self, z):
     # per libsecp256k1 documentation, this helps against side-channel attacks
     if not lib.secp256k1_context_randomize(
             GLOBAL_CTX,
             secrets.token_bytes(32),
     ):
         raise RuntimeError("libsecp256k1 context randomization error")
     secret = int_to_big_endian(self.secret, 32)
     msg = int_to_big_endian(z, 32)
     csig = ffi.new("secp256k1_ecdsa_signature *")
     if not lib.secp256k1_ecdsa_sign(GLOBAL_CTX, csig, msg, secret,
                                     ffi.NULL, ffi.NULL):
         raise RuntimeError("libsecp256k1 ecdsa signing problem")
     sig = Signature(c=csig)
     if not self.point.verify(z, sig):
         raise RuntimeError("generated signature doesn't verify")
     return sig
Esempio n. 13
0
 def __init__(self, csec=None, usec=None):
     if usec:
         self.usec = usec
         self.csec = None
         sec_cache = usec
         self.parity = usec[-1] & 1
     elif csec:
         self.csec = csec
         self.usec = None
         sec_cache = csec
         self.parity = csec[0] - 2
     else:
         raise RuntimeError("need a serialization")
     self.c = ffi.new("secp256k1_pubkey *")
     if not lib.secp256k1_ec_pubkey_parse(GLOBAL_CTX, self.c, sec_cache,
                                          len(sec_cache)):
         raise ValueError("libsecp256k1 produced error")