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
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
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))
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))
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)))