예제 #1
0
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)
예제 #2
0
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()
예제 #3
0
 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()
예제 #4
0
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
예제 #5
0
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()
예제 #6
0
파일: dtc.py 프로젝트: brishtiteveja/Alive
 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)
예제 #7
0
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)
예제 #8
0
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)
예제 #9
0
    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)
예제 #10
0
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,
            }
        })
예제 #11
0
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
예제 #13
0
파일: podle.py 프로젝트: AdamISZ/joinmarket
 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
예제 #14
0
    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))
예제 #15
0
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()
예제 #16
0
 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)
예제 #17
0
    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)
예제 #18
0
    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()
예제 #19
0
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__)
예제 #20
0
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
예제 #21
0
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)
예제 #22
0
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()
예제 #23
0
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)
예제 #25
0
 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))
예제 #26
0
    def keypair():
        """
        Create Key pair

        Returns: bytes, bytes

        """
        sk = secp256k1.PrivateKey()
        return sk.private_key, sk.pubkey.serialize()
예제 #27
0
 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)
예제 #28
0
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)
예제 #30
0
    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)