def sign(key, msg): sig = key.sign(msg) # openssl doesn't return low s, so we have to compute it r, s1 = sigdecode_der(sig) s2 = (secp256k1._r - s1) % secp256k1._r return str(hexlify(sigencode_der(r, s1 if s1 < s2 else s2)), "utf-8")
def f(solved_values, **kwargs): signature_type = kwargs.get("signature_type", DEFAULT_SIGNATURE_TYPE) generator_for_signature_type_f = kwargs[ "generator_for_signature_type_f"] signature_for_hash_type_f = m["signature_for_hash_type_f"] existing_script = kwargs.get("existing_script", b'') existing_signatures, secs_solved = _find_signatures( existing_script, generator_for_signature_type_f, signature_for_hash_type_f, len(m["sig_list"]), m["sec_list"]) sec_keys = m["sec_list"] signature_variables = m["sig_list"] signature_placeholder = kwargs.get("signature_placeholder", DEFAULT_PLACEHOLDER_SIGNATURE) db = kwargs.get("hash160_lookup", {}) # we reverse this enumeration to make the behaviour look like the old signer. BRAIN DAMAGE for signature_order, sec_key in reversed(list(enumerate(sec_keys))): sec_key = solved_values.get(sec_key, sec_key) if sec_key in secs_solved: continue if len(existing_signatures) >= len(signature_variables): break result = db.get(hash160(sec_key)) if result: secret_exponent = result[0] sig_hash = signature_for_hash_type_f(signature_type) generator = result[3] r, s = generator.sign(secret_exponent, sig_hash) else: # try existing signatures generator = generator_for_signature_type_f(signature_type) public_pair = sec_to_public_pair(sec_key, generator=generator) for sig in all_signature_hints(public_pair, signature_for_hash_type_f, **kwargs): sig_hash = signature_for_hash_type_f(indexbytes(sig, -1)) sig_pair = der.sigdecode_der(sig[:-1]) if generator.verify(public_pair, sig_hash, sig_pair): r, s = sig_pair break else: continue order = generator.order() if s + s > order: s = order - s binary_signature = der.sigencode_der(r, s) + int2byte(signature_type) existing_signatures.append((signature_order, binary_signature)) # pad with placeholder signatures if signature_placeholder is not None: while len(existing_signatures) < len(signature_variables): existing_signatures.append((-1, signature_placeholder)) existing_signatures.sort() return dict( zip(signature_variables, (es[-1] for es in existing_signatures)))
def sign(self, h): """ Return a der-encoded signature for a hash h. Will throw a RuntimeError if this key is not a private key """ if not self.is_private(): raise RuntimeError("Key must be private to be able to sign") val = from_bytes_32(h) r, s = self._generator.sign(self.secret_exponent(), val) return sigencode_der(r, s)
def f(solved_values, **kwargs): signature_type = kwargs.get("signature_type", DEFAULT_SIGNATURE_TYPE) signature_hints = kwargs.get("signature_hints", []) generator_for_signature_type_f = kwargs["generator_for_signature_type_f"] signature_for_hash_type_f = m["signature_for_hash_type_f"] existing_script = kwargs.get("existing_script", b'') existing_signatures, secs_solved = _find_signatures( existing_script, generator_for_signature_type_f, signature_for_hash_type_f, len(m["sig_list"]), m["sec_list"]) sec_keys = m["sec_list"] signature_variables = m["sig_list"] signature_placeholder = kwargs.get("signature_placeholder", DEFAULT_PLACEHOLDER_SIGNATURE) db = kwargs.get("hash160_lookup", {}) # we reverse this enumeration to make the behaviour look like the old signer. BRAIN DAMAGE for signature_order, sec_key in reversed(list(enumerate(sec_keys))): sec_key = solved_values.get(sec_key, sec_key) if sec_key in secs_solved: continue if len(existing_signatures) >= len(signature_variables): break result = db.get(hash160(sec_key)) if result: secret_exponent = result[0] sig_hash = signature_for_hash_type_f(signature_type) generator = result[3] r, s = generator.sign(secret_exponent, sig_hash) else: # try existing signatures for sig in signature_hints: sig_hash = signature_for_hash_type_f(indexbytes(sig, -1)) generator = generator_for_signature_type_f(signature_type) public_pair = sec_to_public_pair(sec_key, generator=generator) sig_pair = der.sigdecode_der(sig[:-1]) if generator.verify(public_pair, sig_hash, sig_pair): r, s = sig_pair break else: continue order = generator.order() if s + s > order: s = order - s binary_signature = der.sigencode_der(r, s) + int2byte(signature_type) existing_signatures.append((signature_order, binary_signature)) # pad with placeholder signatures if signature_placeholder is not None: while len(existing_signatures) < len(signature_variables): existing_signatures.append((-1, signature_placeholder)) existing_signatures.sort() return dict(zip(signature_variables, (es[-1] for es in existing_signatures)))
def sigmake(a_key, a_hash_for_sig, a_sig_type=SIGHASH_ALL): """ Signs a_hash_for_sig with a_key and returns a DER-encoded signature with a_sig_type appended. """ order = secp256k1_generator.order() r, s = secp256k1_generator.sign(a_key.secret_exponent(), a_hash_for_sig) if s + s > order: s = order - s return sigencode_der(r, s) + int2byte(a_sig_type)
def sigmake(a_key, a_hash_for_sig, a_sig_type): """ Signs a_hash_for_sig with a_key and returns a DER-encoded signature with a_sig_type appended. """ order = secp256k1_generator.order() r, s = secp256k1_generator.sign(a_key.secret_exponent(), a_hash_for_sig) if s + s > order: s = order - s return sigencode_der(r, s) + int2byte(a_sig_type)
from sys import stdin from pycoin.ecdsa import secp256r1 as p256 from pycoin.encoding import sec, hexbytes from pycoin.satoshi import der from secrets import randbelow from hashlib import sha256 generator = p256.secp256r1_generator privKey = randbelow(generator.order()) pubKey = generator * privKey sec_pub = sec.public_pair_to_sec(pubKey, compressed=False) print("pub: ", hexbytes.b2h(sec_pub)) # message = stdin.read() # message = "Hello, world!" message = "{{\n \"email\": \"[email protected]\",\n \"pubkey\": \"{}\",\n \"scheme\": \"secp256r1\",\n \"nonce\": \"d425dadb98c32e0d23ee3664d4aad64b57debbc062653102b59bd74ce4f64ad7\"\n}}".format( hexbytes.b2h(sec_pub)) digest = sha256(message.encode("utf-8")).digest() msg_hash = int.from_bytes(digest, byteorder="big") signature = generator.sign(privKey, msg_hash) print("message: ", message) # print("priv: ", privKey) der = der.sigencode_der(signature[0], signature[1]) # print("r:", signature[0]) # print("s:", signature[1]) print("sig: ", hexbytes.b2h(der)) valid = generator.verify(pubKey, msg_hash, signature) print("valid: ", valid)