def ecdsa_raw_sign(msg, priv, usehex, rawpriv=True, rawmsg=False, usenonce=None): '''Take the binary message msg and sign it with the private key priv. By default priv is just a 32 byte string, if rawpriv is false it is assumed to be DER encoded. If rawmsg is True, no sha256 hash is applied to msg before signing. In this case, msg must be a precalculated hash (256 bit). If rawmsg is False, the secp256k1 lib will hash the message as part of the ECDSA-SHA256 signing algo. If usenonce is not None, its value is passed to the secp256k1 library sign() function as the ndata value, which is then used in conjunction with a custom nonce generating function, such that the nonce used in the ECDSA sign algorithm is exactly that value (ndata there, usenonce here). 32 bytes. Return value: the calculated signature.''' if rawmsg and len(msg) != 32: raise Exception("Invalid hash input to ECDSA raw sign.") if rawpriv: compressed, p = read_privkey(priv) newpriv = secp256k1.PrivateKey(p, raw=True, ctx=ctx) else: newpriv = secp256k1.PrivateKey(priv, raw=False, ctx=ctx) if usenonce: if len(usenonce) != 32: raise ValueError("Invalid nonce passed to ecdsa_sign: " + str(usenonce)) nf = ffi.addressof(_noncefunc.lib, "nonce_function_rand") ndata = ffi.new("char [32]", usenonce) usenonce = (nf, ndata) sig = newpriv.ecdsa_sign(msg, raw=rawmsg, custom_nonce=usenonce) return newpriv.ecdsa_serialize(sig)
def test_schnorr_partial(): if not secp256k1.HAS_SCHNORR: pytest.skip('secp256k1_schnorr not enabled, skipping') return signer1 = secp256k1.PrivateKey() pubnonce1, privnonce1 = signer1.schnorr_generate_nonce_pair(b'hello') signer2 = secp256k1.PrivateKey() pubnonce2, privnonce2 = signer2.schnorr_generate_nonce_pair(b'hello') # First test partial signatures with only two signers. partial1 = signer1.schnorr_partial_sign(b'hello', privnonce1, pubnonce2) partial2 = signer2.schnorr_partial_sign(b'hello', privnonce2, pubnonce1) blank = secp256k1.PublicKey(flags=secp256k1.NO_FLAGS) sig = blank.schnorr_partial_combine([partial1, partial2]) # Recover the public key from the combined signature. pubkey = secp256k1.PublicKey().schnorr_recover(b'hello', sig) assert blank.public_key is None # Check that the combined public keys from signer1 and signer2 # match the recovered public key. blank.combine( [signer1.pubkey.public_key, signer2.pubkey.public_key]) assert blank.public_key assert secp256k1.PublicKey(pubkey).serialize() == blank.serialize()
def __init__(self, _key_type, secret=None): if isinstance(secret, secp256k1.PrivateKey): self._prvkey = secret elif secret: if len(secret) != self.seed_length: raise Exception('Key must be {} bytes in length'.format( self.seed_length)) self._prvkey = secp256k1.PrivateKey(secret, raw=True) else: self._prvkey = secp256k1.PrivateKey()
def verify(message, signature, pubkey): """ Args: message: Message string signature: DER encoded compact signature pubkey: A serialized Public Key string Returns: boolean True / False """ verified = False try: pubkey = _decode_pubkey(pubkey, 'hex') if isinstance(message, str): message = message.encode('utf-8') try: # check python3 signature = bytes.fromhex(signature) except (ValueError, AttributeError): signature = binascii.unhexlify(signature) sig = secp256k1.PrivateKey().ecdsa_deserialize_compact(signature) verified = pubkey.ecdsa_verify(message, sig) # Fail Securely (even if it's not pythonic) # pylint: disable=broad-except except Exception: return False return verified
def test_schnorr_simple(): if not secp256k1.HAS_SCHNORR: pytest.skip('secp256k1_schnorr not enabled, skipping') return inst = secp256k1.PrivateKey() raw_sig = inst.schnorr_sign(b'hello') assert inst.pubkey.schnorr_verify(b'hello', raw_sig) key2 = secp256k1.PrivateKey() assert not key2.pubkey.schnorr_verify(b'hello', raw_sig) blank = secp256k1.PublicKey() pubkey = blank.schnorr_recover(b'hello', raw_sig) pub = secp256k1.PublicKey(pubkey) assert pub.serialize() == inst.pubkey.serialize()
def auth(self, username, private_key): # TODO: Move API to settings page accessible from anywhere in app avalon_account = requests.get('http://192.168.0.186:3003/account/' + username) if avalon_account.status_code != 200: self.avalonLoginResult.emit(2) try: public_key = base58.b58encode( secp256k1.PrivateKey(base58.b58decode( private_key)).pubkey.serialize()).decode('UTF-8') except: self.avalonLoginResult.emit(3) if avalon_account.json()['pub'] != public_key: valid_key = False for i in range(0, len(avalon_account.json()['keys'])): # TODO: Update with the correct op # on livestreaming HF if avalon_account.json( )['keys'][i]['pub'] == public_key and all( x in avalon_account.json()['keys'][i]['types'] for x in [19, 20]): # avalon_keyid = avalon_account.json()['keys'][i]['id'] valid_key = True break if valid_key == False: self.avalonLoginResult.emit(3) else: self.avalonLoginResult.emit(0) else: self.avalonLoginResult.emit(1)
def customgen(): #~ i = randint(1, 115792089237316195423570985008687907852837564279074904382605163141518161494336) #~ BrtSecp.pubkeyy(i) pk = secp256k1.PrivateKey() pubbin = pk.pubkey.serialize(False) pubkey = binascii.hexlify(pubbin) address = gen_address(pubkey)
def _decode_pubkey(serialized_pubkey, encoding_format='hex'): if encoding_format == 'hex': serialized_pubkey = binascii.unhexlify(serialized_pubkey) elif encoding_format != 'bytes': raise ValueError("Unrecognized pubkey encoding format") pub = secp256k1.PrivateKey().pubkey.deserialize(serialized_pubkey) return secp256k1.PublicKey(pub)
def from_secret_exponent(cls, secret_exponent: bytes, curve=b'ed', activation_code=None): """ Creates a key object from a secret exponent. :param secret_exponent: secret exponent or seed :param curve: b'sp' for Secp251k1, b'p2' for P256/Secp256r1, b'ed' for Ed25519 (default) :param activation_code: secret for initializing account balance """ # Ed25519 if curve == b'ed': # Dealing with secret exponent or seed? if len(secret_exponent) == 64: public_point = pysodium.crypto_sign_sk_to_pk( sk=secret_exponent) else: public_point, secret_exponent = pysodium.crypto_sign_seed_keypair( seed=secret_exponent) # Secp256k1 elif curve == b'sp': sk = secp256k1.PrivateKey(secret_exponent) public_point = sk.pubkey.serialize() # P256 elif curve == b'p2': pk = get_public_key(bytes_to_int(secret_exponent), curve=P256) public_point = SEC1Encoder.encode_public_key(pk) else: assert False return cls(public_point, secret_exponent, curve=curve, activation_code=activation_code)
def cmd_login(): 'Change BL4P login settings' #TODO (bug 14): make URL configurable url = 'ws://localhost:8000/' currentConfig = rpc.call('bl4p.getconfig', {})['values'] signingPrivateKeyHex = currentConfig['bl4p.signingPrivateKey'] if signingPrivateKeyHex == '': print('We don\'t have a signing key yet; generating a new one.') signingPrivateKeyHex = os.urandom(32).hex() rpc.call( 'bl4p.setconfig', {'values': { 'bl4p.signingPrivateKey': signingPrivateKeyHex, }}) pk = secp256k1.PrivateKey(privkey=bytes.fromhex(signingPrivateKeyHex)) signingPublicKey = pk.pubkey.serialize() print('Public key (hex-encoded): ', signingPublicKey.hex()) apiKey = input('API key? ') apiSecret = input('API secret (base64-encoded): ') return rpc.call( 'bl4p.setconfig', { 'values': { 'bl4p.url': url, 'bl4p.apiKey': apiKey, 'bl4p.apiSecret': apiSecret, } })
def test_ecdsa_recover(): if not secp256k1.HAS_RECOVERABLE: pytest.skip('secp256k1_recovery not enabled, skipping') return class MyECDSA(secp256k1.Base, secp256k1.ECDSA): def __init__(self): secp256k1.Base.__init__(self, ctx=None, flags=secp256k1.ALL_FLAGS) privkey = secp256k1.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 = secp256k1.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 = secp256k1.PublicKey(pubkey2).serialize() assert pubser == pubser2 raw_sig = unrelated.ecdsa_recoverable_convert(recsig2) unrelated.ecdsa_deserialize(unrelated.ecdsa_serialize(raw_sig))
def getG(compressed=True): """Returns the public key binary representation of secp256k1 G """ priv = "\x00" * 31 + "\x01" G = secp256k1.PrivateKey(priv, ctx=ctx).pubkey.serialize(compressed) return G
def verify(self, commitment, index_range): """For an object created without a private key, check that the opened commitment verifies for at least one NUMS point as defined by the range in index_range """ if not all([self.P, self.P2, self.s, self.e]): raise PoDLE("Verify called without sufficient data") if not self.get_commitment() == commitment: return False for J in [getNUMS(i) for i in index_range]: sig_priv = secp256k1.PrivateKey(self.s, raw=True, ctx=ctx) sG = sig_priv.pubkey sJ = J.tweak_mul(self.s) e_int = decode(self.e, 256) minus_e = encode(-e_int % N, 256, minlen=32) minus_e_P = self.P.tweak_mul(minus_e) minus_e_P2 = self.P2.tweak_mul(minus_e) KG = dummy_pub.combine([sG.public_key, minus_e_P.public_key]) KJ = dummy_pub.combine([sJ.public_key, minus_e_P2.public_key]) KGser = secp256k1.PublicKey(KG, ctx=ctx).serialize() KJser = secp256k1.PublicKey(KJ, ctx=ctx).serialize() #check 2: e =?= H(K_G || K_J || P || P2) e_check = hashlib.sha256(KGser + KJser + self.P.serialize() + self.P2.serialize()).digest() if e_check == self.e: return True #commitment fails for any NUMS in the provided range return False
def read_from_file(cls, file_name, search_path=['.', './keys']): full_file = putils.find_file_in_path(file_name, search_path) with open(full_file, "r") as ff: hex_encoded_private_key = ff.read() priv = binascii.unhexlify(hex_encoded_private_key) return cls(secp256k1.PrivateKey(priv))
def test_pubkey_combine(): k1 = secp256k1.PrivateKey() k2 = secp256k1.PrivateKey() pub1 = k1.pubkey.public_key pub2 = k2.pubkey.public_key new = secp256k1.PublicKey() assert new.public_key is None res = new.combine([pub1, pub2]) assert new.public_key == res new = secp256k1.PublicKey() assert new.public_key is None res = new.combine([pub1]) assert new.public_key == res assert new.serialize() == k1.pubkey.serialize()
def signature(self, key): raw_tx = self.serialize() sk_str = b58decode_check(key)[4:] pk = secp256k1.PrivateKey(sk_str) signature = pk.ecdsa_serialize_compact( pk.ecdsa_sign(b'\x03' + unhexlify(raw_tx), digest=blake2b_32)) return hexlify(signature)
def from_secret_key(cls, secret_key: bytes, curve=b'ed'): """ Creates a key object from a secret exponent. :param secret_key: secret exponent or seed :param curve: an elliptic curve used, default is ed25519 """ # Ed25519 if curve == b'ed': # Dealing with secret key or seed? if len(secret_key) == 64: public_key = pysodium.crypto_sign_sk_to_pk(sk=secret_key) else: public_key, secret_key = pysodium.crypto_sign_seed_keypair(seed=secret_key) # Secp256k1 elif curve == b'sp': sk = secp256k1.PrivateKey(secret_key) public_key = sk.pubkey.serialize() # P256 elif curve == b'p2': pk = get_public_key(bytes_to_int(secret_key), curve=P256) public_key = SEC1Encoder.encode_public_key(pk) else: assert False return cls(public_key, secret_key, curve=curve)
def sign(self, message, generic=False): """ Sign a raw sequence of bytes :param message: sequence of bytes, raw format or hexadecimal notation :param generic: do not specify elliptic curve if set to True :return: signature in base58 encoding """ message = scrub_input(message) if not self.is_secret: raise ValueError("Cannot sign without a secret key.") # Ed25519 if self.curve == b"ed": digest = pysodium.crypto_generichash(message) signature = pysodium.crypto_sign_detached(digest, self._secret_key) # Secp256k1 elif self.curve == b"sp": pk = secp256k1.PrivateKey(self._secret_key) signature = pk.ecdsa_serialize_compact( pk.ecdsa_sign(message, digest=blake2b_32)) # P256 elif self.curve == b"p2": r, s = sign(msg=message, d=bytes_to_int(self._secret_key), hashfunc=blake2b_32) signature = int_to_bytes(r) + int_to_bytes(s) else: assert False if generic: prefix = b'sig' else: prefix = self.curve + b'sig' return base58_encode(signature, prefix).decode()
def _decode_private_key(encoded_private_key, encoding_format='wif'): """ Args: encoded_private_key: an encoded private key string encoding_format: string indicating format such as 'wif' Returns: priv (bytes): bytes representation of the private key """ if encoding_format == 'wif': # int to hex string priv = pybitcointools.encode_privkey(encoded_private_key, 'hex') # hex string to bytes try: # check python 3 priv = priv.to_bytes(32, byteorder='big') except AttributeError: priv = binascii.unhexlify(priv) elif encoding_format == 'hex': try: priv = encoded_private_key.to_bytes(32, byteorder='big') except AttributeError: priv = binascii.unhexlify(encoded_private_key) elif encoding_format == 'bytes': priv = encoded_private_key else: raise TypeError("unsupported private key format") return secp256k1.PrivateKey(priv, ctx=__CTX__)
def create_mnb(mne): collat_outpoint = Transaction.COutPoint(serialize.hs2b(mne['txid']), mne['nout']) mnp = Masternode.CMasternodePing(collat_outpoint) mn_privkey = energi.decode_address(mne['mn_privkey']) block_hash = Masternode.get_block_hash(13) mnp.sign(block_hash, mn_privkey) mnb = Masternode.CMasternodeBroadcast() mnb.outpoint = collat_outpoint mnb.addr = parse_ipport(mne['ip']) mn_private_key = secp256k1.PrivateKey(mn_privkey, raw = True) mn_public_key = mn_private_key.pubkey.serialize(compressed = False) co_ae = walletdb.get_addr_txid(mne['txid'], mne['nout']) if co_ae is None: raise RuntimeError('cannot find address for txid: %s' % mne['txid']) co_public_key = co_ae['pubkey'] mnb.pubkey_collateral = energi.compress_public_key(co_public_key) mnb.pubkey_masternode = mn_public_key mnb.last_ping = mnp print('Signing on ledger:') mnb.hw_sign(energi.serialize_pathd(co_ae)) print('MasternodeBroadcast:\n%s' % mnb) return mnb
def generate_privkey(privkey_format='wif'): """ Create a random private key Args: privkey_format: the format to export the key ('wif', 'hex', or 'bytes') Returns: Serialized private key suitable for subsequent calls to e.g. sign(). """ return _encode_privkey(secp256k1.PrivateKey(ctx=__CTX__), privkey_format)
def generate_wallet(): priv_key: secp256k1.PrivateKey = secp256k1.PrivateKey() pub_key: secp256k1.PublicKey = priv_key.pubkey byte_arr = pub_key.serialize(compressed=True) s = hashlib.new("sha256", byte_arr).digest() r = hashlib.new("ripemd160", s).digest() bech_addr = bech32.bech32_encode("cosmos", bech32.convertbits(r, 8, 5)) return bech_addr, byte_arr.hex(), priv_key.serialize()
def CreatePdoSawtoothSigner(private_key_str, pdo_crypto=False): if not pdo_crypto: if not private_key_str: sk = secp256k1.PrivateKey(ctx=__CTX__) return SignerSecp256k1Lib(sk) else: try: sk = binascii.unhexlify(private_key_str) return SignerSecp256k1Lib(secp256k1.PrivateKey(sk, ctx=__CTX__)) except Exception as e: raise ClientConnectException( 'Unable to parse hex private key: {}'.format(e)) else: # TODO: add PDO crypto lib support here raise ClientConnectException('PDO Crypto is not supported')
def ecdsa_raw_sign(msg, priv, usehex, rawpriv=True, rawmsg=False, usenonce=None, formsg=False): '''Take the binary message msg and sign it with the private key priv. By default priv is just a 32 byte string, if rawpriv is false it is assumed to be hex encoded (note only works if usehex=False). If rawmsg is True, no sha256 hash is applied to msg before signing. In this case, msg must be a precalculated hash (256 bit). If rawmsg is False, the secp256k1 lib will hash the message as part of the ECDSA-SHA256 signing algo. If usenonce is not None, its value is passed to the secp256k1 library sign() function as the ndata value, which is then used in conjunction with a custom nonce generating function, such that the nonce used in the ECDSA sign algorithm is exactly that value (ndata there, usenonce here). 32 bytes. Return value: the calculated signature.''' if rawmsg and len(msg) != 32: raise Exception("Invalid hash input to ECDSA raw sign.") if rawpriv: compressed, p = read_privkey(priv) newpriv = secp256k1.PrivateKey(p, raw=True, ctx=ctx) else: newpriv = secp256k1.PrivateKey(priv, raw=False, ctx=ctx) if formsg: sig = newpriv.ecdsa_sign_recoverable(msg, raw=rawmsg) s, rid = newpriv.ecdsa_recoverable_serialize(sig) return chr(31 + rid) + s #Donations, thus custom nonce, currently disabled, hence not covered. elif usenonce: #pragma: no cover raise NotImplementedError #if len(usenonce) != 32: # raise ValueError("Invalid nonce passed to ecdsa_sign: " + str( # usenonce)) #nf = ffi.addressof(_noncefunc.lib, "nonce_function_rand") #ndata = ffi.new("char [32]", usenonce) #usenonce = (nf, ndata) #sig = newpriv.ecdsa_sign(msg, raw=rawmsg, custom_nonce=usenonce) else: #partial fix for secp256k1-transient not including customnonce; #partial because donations will crash on windows in the "if". sig = newpriv.ecdsa_sign(msg, raw=rawmsg) return newpriv.ecdsa_serialize(sig)
def from_wif(wif): """Decodes a PrivateKey from a wif-encoded string """ try: priv = pybitcointools.encode_privkey(wif, 'hex') priv = binascii.unhexlify(priv) return Secp256k1PrivateKey(secp256k1.PrivateKey(priv, ctx=__CTX__)) except Exception as e: raise ParseError('Unable to parse wif key: {}'.format(e))
def keypair(): """ Create Key pair Returns: bytes, bytes """ sk = secp256k1.PrivateKey() return sk.private_key, sk.pubkey.serialize()
def gen(self): values = [] pk = secp256k1.PrivateKey() pubbin = pk.pubkey.serialize(False) pubkey = binascii.hexlify(pubbin) address = self.gen_address(pubkey) values.append(pk.private_key) values.append(address) self.rows.append(values)
def get_eth_addr(private_key_str=None): if private_key_str is None: private_key = secp256k1.PrivateKey() private_key_str = private_key.serialize() else: private_key_bytes = bytes.fromhex(private_key_str) private_key = secp256k1.PrivateKey(private_key_bytes) public_key_bytes = private_key.pubkey.serialize(compressed=False) public_key_str = public_key_bytes.hex() keccak_hash = keccak.new(digest_bits=256) keccak_hash.update(public_key_bytes[1:]) h = keccak_hash.hexdigest() address = '0x' + h[-40:] return { "private_key": private_key_str, # "public_key": public_key_str, "address": address }
def privkey_to_pubkey_inner(priv, usehex): '''Take 32/33 byte raw private key as input. If 32 bytes, return compressed (33 byte) raw public key. If 33 bytes, read the final byte as compression flag, and return compressed/uncompressed public key as appropriate.''' compressed, priv = read_privkey(priv) #secp256k1 checks for validity of key value. newpriv = secp256k1.PrivateKey(privkey=priv, ctx=ctx) return newpriv.pubkey.serialize(compressed=compressed)
def login(self, account, wifkey): try: self.wif = wifkey pKey = PrivateKey(wifkey) except: raise InvalidWifKey p = bytes(pKey) pub_key = format(pKey.pubkey, 'BTS') auth_data = { "account": account, "site": 'btsbots.com', "time": time.time() } message = json.dumps(auth_data, sort_keys=True).encode('utf-8') digest = hashlib.sha256(message).digest() i = 0 ndata = secp256k1.ffi.new("const int *ndata") ndata[0] = 0 while True: ndata[0] += 1 privkey = secp256k1.PrivateKey(p, raw=True) sig = secp256k1.ffi.new('secp256k1_ecdsa_recoverable_signature *') signed = secp256k1.lib.secp256k1_ecdsa_sign_recoverable( privkey.ctx, sig, digest, privkey.private_key, secp256k1.ffi.NULL, ndata) assert signed == 1 signature, i = privkey.ecdsa_recoverable_serialize(sig) if _is_canonical(signature): i += 4 # compressed i += 27 # compact break # pack signature # sigstr = struct.pack("<B", i) sigstr += signature login_data = { "user": account, "pubkey": pub_key, "verify": { "data": json.dumps(auth_data, sort_keys=True), "signature": hexlify(sigstr).decode('ascii') } } def logged_in(error, data): if error: print(error) # raise LoginFailed else: self.account = account self.ddp_client.subscribe('price') self.ddp_client.subscribe('login_order', params=[account]) self.ddp_client.subscribe('login_balance', params=[account]) self.ddp_client._login(login_data, logged_in)