Ejemplo n.º 1
0
 def __init__(self,
              u=None,
              priv=None,
              P=None,
              P2=None,
              s=None,
              e=None,
              used=False):
     #This class allows storing of utxo in format "txid:n" only for
     #convenience of storage/access; it doesn't check or use the data.
     #Arguments must be provided in hex.
     self.u = u
     if not priv:
         if P:
             #Construct a pubkey from raw hex
             self.P = secp256k1.PublicKey(safe_from_hex(P),
                                          raw=True,
                                          ctx=ctx)
         else:
             self.P = None
     else:
         if P:
             raise PoDLEError("Pubkey should not be provided with privkey")
         #any other formatting abnormality will just throw in PrivateKey
         if len(priv) == 66 and priv[-2:] == '01':
             priv = priv[:-2]
         self.priv = secp256k1.PrivateKey(safe_from_hex(priv), ctx=ctx)
         self.P = self.priv.pubkey
     if P2:
         self.P2 = secp256k1.PublicKey(safe_from_hex(P2), raw=True, ctx=ctx)
     else:
         self.P2 = None
     #These sig values should be passed in hex.
     if s:
         self.s = safe_from_hex(s)
     if e:
         self.e = safe_from_hex(e)
     #Optionally maintain usage state (boolean)
     self.used = used
     #the H(P2) value
     self.commitment = None
Ejemplo n.º 2
0
def verify_message(message, signature, hashfn=hashlib.sha256):
    if not isinstance(message, bytes_types):
        message = py23_bytes(message, "utf-8")
    if not isinstance(signature, bytes_types):
        signature = py23_bytes(signature, "utf-8")
    if not isinstance(message, bytes_types):
        raise AssertionError()
    if not isinstance(signature, bytes_types):
        raise AssertionError()
    digest = hashfn(message).digest()
    sig = signature[1:]
    recoverParameter = bytearray(
        signature)[0] - 4 - 27  # recover parameter only

    if SECP256K1_MODULE == "secp256k1":
        ALL_FLAGS = secp256k1.lib.SECP256K1_CONTEXT_VERIFY | secp256k1.lib.SECP256K1_CONTEXT_SIGN
        # Placeholder
        pub = secp256k1.PublicKey(flags=ALL_FLAGS)
        # Recover raw signature
        sig = pub.ecdsa_recoverable_deserialize(sig, recoverParameter)
        # Recover PublicKey
        verifyPub = secp256k1.PublicKey(pub.ecdsa_recover(message, sig))
        # Convert recoverable sig to normal sig
        normalSig = verifyPub.ecdsa_recoverable_convert(sig)
        # Verify
        verifyPub.ecdsa_verify(message, normalSig)
        phex = verifyPub.serialize(compressed=True)
    elif SECP256K1_MODULE == "cryptography":
        p = recover_public_key(digest, sig, recoverParameter, message)
        order = ecdsa.SECP256k1.order
        r, s = ecdsa.util.sigdecode_string(sig, order)
        sigder = encode_dss_signature(r, s)
        p.verify(sigder, message, ec.ECDSA(hashes.SHA256()))
        phex = compressedPubkey(p)
    else:
        p = recover_public_key(digest, sig, recoverParameter)
        # Will throw an exception of not valid
        p.verify_digest(sig, digest, sigdecode=ecdsa.util.sigdecode_string)
        phex = compressedPubkey(p)

    return phex
Ejemplo n.º 3
0
    def _public_key_bytes_to_object(public_key):
        """
        Public key bytes to object.

        Args:
            public_key (bytes): secp256k1 public key in bytes

        Returns:
            public key object
        """
        return Secp256k1PublicKey(
            secp256k1.PublicKey(public_key, raw=True, ctx=__CTX__))
Ejemplo n.º 4
0
 def __init__(self, pubkey=None, raw=False, flags=None, ctx=None):
     if USE_SECP:
         if flags == None:
             flags = secp256k1.FLAG_VERIFY
         self.obj = secp256k1.PublicKey(pubkey, raw, flags, ctx)
     else:
         if not raw:
             raise Exception("Non raw init unsupported")
         pubkey = pubkey[1:]
         x = int.from_bytes(pubkey[0:32], 'big')
         y = int.from_bytes(pubkey[32:], 'big')
         self.obj = ECPublicKey(Point(x, y, CURVE_SECP256K1))
Ejemplo n.º 5
0
def convert_azure_secp256k1_signature_to_vrs(pub_key_bytes,
                                             msg_hash_bytes,
                                             sig_bytes,
                                             chain_id=0):
    sig_bytes = bytes(make_canonical(sig_bytes))

    # Check the signature is still valid
    ecdsa_pubkey = secp256k1.PublicKey(pubkey=pub_key_bytes, raw=True)
    if len(sig_bytes) < 64:
        return 0, 0, 0, False
    sig_ser = ecdsa_pubkey.ecdsa_deserialize_compact(sig_bytes)
    verified_ecdsa = ecdsa_pubkey.ecdsa_verify(msg_hash_bytes,
                                               sig_ser,
                                               raw=True)

    v = -1
    unrelated = MyECDSA()
    for i in range(0, 2):
        recsig = unrelated.ecdsa_recoverable_deserialize(sig_bytes, i)
        pubkey_recovered = unrelated.ecdsa_recover(msg_hash_bytes,
                                                   recsig,
                                                   raw=True)
        pubser = secp256k1.PublicKey(pubkey_recovered).serialize(
            compressed=False)
        if pubser == pub_key_bytes:
            v = i
            break

    assert v == 0 or v == 1

    v += 27

    if chain_id > 0:
        v += chain_id * 2 + 8

    r = sig_bytes[0:32]
    s = sig_bytes[32:64]
    v = v

    return v, int_from_bytes(r), int_from_bytes(s), True
 def verify_deprecated(self, message):
     pub = secp256k1.PublicKey(self.pub_key, raw=True)
     message = VarInt(len(message)).encode() + message
     print("message", message)
     # LOGGER.debug("Comparing with %r" % (MESSAGE_TEMPLATE.format(message).encode()))
     try:
         sig_raw = pub.ecdsa_deserialize(self.sig_ser)
         good = pub.ecdsa_verify(
             MESSAGE_TEMPLATE.format(message).encode(), sig_raw)
     except Exception:
         LOGGER.exception("Verification failed")
         good = False
     return good
Ejemplo n.º 7
0
def multiply(s, pub, usehex, rawpub=True):
    '''Input binary compressed pubkey P(33 bytes)
    and scalar s(32 bytes), return s*P.
    The return value is a binary compressed public key.
    Note that the called function does the type checking
    of the scalar s.
    ('raw' options passed in)
    '''
    newpub = secp256k1.PublicKey(pub, raw=rawpub, ctx=ctx)
    #see note to "tweak_mul" function in podle.py
    res = secp256k1._tweak_public(newpub,
                                  secp256k1.lib.secp256k1_ec_pubkey_tweak_mul,
                                  s)
    return res.serialize()
Ejemplo n.º 8
0
    def verify(data, signature, pk):
        """
        Verify if the signature of data matches the public key
        Args:
            data(bytes): data for signature
            signature(bytes): signature of the data
            pk(bytes): public key

        Returns: boolean

        """
        pk_object = secp256k1.PublicKey(pubkey=pk, raw=True)
        result = pk_object.ecdsa_verify(data, signature)
        return result
Ejemplo n.º 9
0
 def recover_pubkey_parameter(self, digest, signature, pubkey):
     for i in range(0, 4):
         if USE_SECP256K1:
             sig = pubkey.ecdsa_recoverable_deserialize(signature, i)
             p = secp256k1.PublicKey(pubkey.ecdsa_recover(
                 self.message, sig))
             if p.serialize() == pubkey.serialize():
                 return i
         else:
             p = self.recover_public_key(digest, signature, i)
             if (p.to_string() == pubkey.to_string()
                     or self.compressed_pubkey(p) == pubkey.to_string()):
                 return i
     return None
Ejemplo n.º 10
0
def hw_sign(keypath, msg_b):
    ledger_sig, recid = ledger.call_sign_mnb(keypath, msg_b, recoverable=True)
    pubkey = secp256k1.PublicKey(raw=True, flags=secp256k1.ALL_FLAGS)
    compact_sig = pubkey.ecdsa_serialize_compact(
        pubkey.ecdsa_deserialize(ledger_sig))

    is_compressed = True
    recoverable_sig = bytes([27 + recid +
                             (4 if is_compressed else 0)]) + compact_sig

    if not verify_sig(msg_b, recoverable_sig, raw=False):
        raise RuntimeError('could not verify signature')

    return recoverable_sig
Ejemplo n.º 11
0
 def get_public_key_from_wif(cls, buf):
     if len(buf) <= 3:
         raise CipherException("The length of buffer should be "
                               "larger than 3")
     if buf[:3] != b"COS":
         raise CipherException("The prefix of buffer should be \'COS\'")
     buf = base58.b58decode(buf[3:])
     if len(buf) <= 4:
         raise CipherException("The length of decoded buffer should be "
                               "larger than 4")
     data, vinfo = buf[:-4], buf[-4:]
     data_hash = SHA256.new(data=SHA256.new(data=data).digest())
     if vinfo != data_hash.digest()[:4]:
         raise CipherException("Couldn't verify public key")
     return secp256k1.PublicKey(pubkey=data, raw=True)
Ejemplo n.º 12
0
 def recoverPubkeyParameter(self, digest, signature, pubkey):
     """Use to derive a number that allows to easily recover the public key from the signature."""
     for i in range(0, 4):
         if USE_SECP256K1:
             sig = pubkey.ecdsa_recoverable_deserialize(signature, i)
             p = secp256k1.PublicKey(pubkey.ecdsa_recover(
                 self.message, sig))
             if p.serialize() == pubkey.serialize():
                 return i
         else:
             p = self.recover_public_key(digest, signature, i)
             if p.to_string() == pubkey.to_string(
             ) or self.compressedPubkey(p) == pubkey.to_string():
                 return i
     return None
Ejemplo n.º 13
0
    def set_public_key(self, public_key_string: str) -> None:
        """Sets the public key (and clears the private key) for this instantiation of the class
        Note: This must be called AFTER self.encryption (set_encryption) is already set
        Args:
            public_key_string: base58 encoded public key string (public dragonchain id)
        Raises:
            NotImplementedError when invalid encryption_type
        """
        decoded_key = base58.b58decode(public_key_string)
        # Modify this statement as support for other encryption algorithms change
        if self.encryption == crypto.SupportedEncryption.secp256k1:
            self.pub = secp256k1.PublicKey(pubkey=decoded_key, raw=True)
        else:
            raise NotImplementedError("Encryption algorithm not implemented")

        self.priv = None
Ejemplo n.º 14
0
    def verify(self, signature: Union[str, bytes],
               message: Union[str, bytes]) -> None:
        """Verify signature, raise exception if it is not valid.

        :param message: sequance of bytes, raw format or hexadecimal notation
        :param signature: a signature in base58 encoding
        :raises: ValueError if signature is not valid
        """
        encoded_signature = scrub_input(signature)
        encoded_message = scrub_input(message)

        if not self.public_point:
            raise ValueError("Cannot verify without a public key")

        if encoded_signature[:3] != b'sig':  # not generic
            if self.curve != encoded_signature[:2]:  # "sp", "p2" "ed"
                raise ValueError("Signature and public key curves mismatch.")

        decoded_signature = base58_decode(encoded_signature)

        # Ed25519
        if self.curve == b"ed":
            digest = pysodium.crypto_generichash(encoded_message)
            try:
                pysodium.crypto_sign_verify_detached(decoded_signature, digest,
                                                     self.public_point)
            except ValueError as exc:
                raise ValueError('Signature is invalid.') from exc
        # Secp256k1
        elif self.curve == b"sp":
            pk = secp256k1.PublicKey(self.public_point, raw=True)
            sig = pk.ecdsa_deserialize_compact(decoded_signature)
            if not pk.ecdsa_verify(encoded_message, sig, digest=blake2b_32):
                raise ValueError('Signature is invalid.')
        # P256
        elif self.curve == b"p2":
            pk = fastecdsa.encoding.sec1.SEC1Encoder.decode_public_key(
                self.public_point, curve=fastecdsa.curve.P256)
            r, s = bytes_to_int(decoded_signature[:32]), bytes_to_int(
                decoded_signature[32:])
            if not fastecdsa.ecdsa.verify(
                    sig=(r, s), msg=encoded_message, Q=pk,
                    hashfunc=blake2b_32):
                raise ValueError('Signature is invalid.')
        else:
            raise Exception(
                f'Unknown elliptic curve {self.curve}')  # type: ignore
Ejemplo n.º 15
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')

    partial1 = signer1.schnorr_partial_sign(b'hello', privnonce1, pubnonce2)
    blank = secp256k1.PublicKey(flags=secp256k1.NO_FLAGS)

    with pytest.raises(TypeError):
        blank.schnorr_partial_combine([partial1, secp256k1.ffi.NULL])

    with pytest.raises(Exception):
        blank.schnorr_partial_combine([partial1, b''])
def ecdsa_raw_verify(msg, pub, sig, usehex, rawmsg=False):
    '''Take the binary message msg and binary signature sig,
    and verify it against the pubkey pub.
    If rawmsg is True, no sha256 hash is applied to msg before verifying.
    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 verification algo.
    Return value: True if the signature is valid for this pubkey, False
    otherwise.
    Since the arguments may come from external messages their content is
    not guaranteed, so return False on any parsing exception.
    '''
    try:
        if rawmsg:
            assert len(msg) == 32
        newpub = secp256k1.PublicKey(pubkey=pub, raw=True, ctx=ctx)
        sigobj = newpub.ecdsa_deserialize(sig)
        retval = newpub.ecdsa_verify(msg, sigobj, raw=rawmsg)
    except:
        return False
    return retval
Ejemplo n.º 17
0
    def verify(self, signature, message):
        """
        Verify signature, raise exception if it is not valid
        :param message: sequance of bytes, raw format or hexadecimal notation
        :param signature: a signature in base58 encoding
        """
        signature = scrub_input(signature)
        message = scrub_input(message)

        if not self.public_point:
            raise ValueError("Cannot verify without a public key")

        if signature[:3] != b'sig':  # not generic
            if self.curve != signature[:2]:  # "sp", "p2" "ed"
                raise ValueError("Signature and public key curves mismatch.")

        signature = base58_decode(signature)

        # Ed25519
        if self.curve == b"ed":
            digest = pysodium.crypto_generichash(message)
            try:
                pysodium.crypto_sign_verify_detached(signature, digest,
                                                     self.public_point)
            except ValueError:
                raise ValueError('Signature is invalid.')
        # Secp256k1
        elif self.curve == b"sp":
            pk = secp256k1.PublicKey(self.public_point, raw=True)
            sig = pk.ecdsa_deserialize_compact(signature)
            if not pk.ecdsa_verify(message, sig, digest=blake2b_32):
                raise ValueError('Signature is invalid.')
        # P256
        elif self.curve == b"p2":
            pk = SEC1Encoder.decode_public_key(self.public_point, curve=P256)
            r, s = bytes_to_int(signature[:32]), bytes_to_int(signature[32:])
            if not verify(sig=(r, s), msg=message, Q=pk, hashfunc=blake2b_32):
                raise ValueError('Signature is invalid.')
        else:
            assert False
Ejemplo n.º 18
0
def test_publickey():
    with pytest.raises(Exception):
        # Must be bytes.

        # In Python 2 this will not raise a TypeError
        # since bytes is an alias to str, instead it will fail
        # during deserialization.
        secp256k1.PublicKey('abc', raw=True)
    with pytest.raises(Exception):
        secp256k1.PublicKey([], raw=True)

    with pytest.raises(Exception):
        # Invalid size.
        secp256k1.PublicKey(b'abc', raw=True)

    with pytest.raises(Exception):
        # Invalid public key.
        secp256k1.PublicKey(b'a' * 33, raw=True)

    # Invalid usage: passing a raw public key but not specifying raw=True.
    with pytest.raises(TypeError):
        secp256k1.PublicKey(b'a' * 33)

    # No public key.
    assert secp256k1.PublicKey()

    pub1 = secp256k1.PrivateKey().pubkey.public_key
    new = secp256k1.PublicKey()
    with pytest.raises(AssertionError):
        # Trying to combine with something that is not a public key.
        new.combine([pub1, secp256k1.ffi.NULL])

    new = secp256k1.PublicKey()
    with pytest.raises(AssertionError):
        # Nothing to combine.
        new.combine([])
Ejemplo n.º 19
0
    def verify(self):
        try:
            pub_key = secp256k1.PublicKey()
            pub_key.deserialize(self.get_public_key())

            assert pub_key.public_key, "No public key defined"

            if pub_key.flags & lib.SECP256K1_CONTEXT_VERIFY != \
               lib.SECP256K1_CONTEXT_VERIFY:
                raise Exception("instance not configured for sig verification")

            msg_digest = self.get_hashing_algorithm()(
                self._entity_hash).digest()
            raw_sig = pub_key.ecdsa_deserialize_compact(
                self._entity_hash_signature)

            verified = lib.secp256k1_ecdsa_verify(
                pub_key.ctx, raw_sig, msg_digest, pub_key.public_key)
        except Exception as e:
            LOGGER.exception(e)
            return False
        else:
            return bool(verified)
Ejemplo n.º 20
0
def ecrecover_to_pub(rawhash, v, r, s):
    if secp256k1:
        # Legendre symbol check; the secp256k1 library does not seem to do this
        pk = secp256k1.PublicKey(flags=secp256k1.ALL_FLAGS)
        xc = r * r * r + 7
        assert pow(xc, (SECP256K1P - 1) // 2, SECP256K1P) == 1
        try:
            pk.public_key = pk.ecdsa_recover(
                rawhash,
                pk.ecdsa_recoverable_deserialize(
                    zpad(bytearray_to_bytestr(int_to_32bytearray(r)), 32) +
                    zpad(bytearray_to_bytestr(int_to_32bytearray(s)), 32),
                    v - 27
                ),
                raw=True
            )
            pub = pk.serialize(compressed=False)[1:]
        except:
            pub = b"\x00" * 64
    else:
        recovered_addr = ecdsa_raw_recover(rawhash, (v, r, s))
        pub = encode_pubkey(recovered_addr, 'bin_electrum')
    assert len(pub) == 64
    return pub
Ejemplo n.º 21
0
def _main():
    if len(sys.argv) != 4:
        print("usage: {} public data signature".format(sys.argv[0]),
              file=sys.stderr)
        sys.exit(1)

    data = Path(sys.argv[2]).read_bytes()
    pubkey_compressed = bytes(
        int(x, 16) for x in Path(sys.argv[1]).read_text().strip().split(",")
        if x)
    signature_raw = bytes(
        int(x, 16) for x in Path(sys.argv[3]).read_text().strip().split(",")
        if x)
    pubkey = secp256k1.PublicKey(pubkey_compressed, raw=True)
    signature = pubkey.ecdsa_deserialize_compact(signature_raw)
    was_normalized, normalized = pubkey.ecdsa_signature_normalize(signature)

    if was_normalized:
        print("Signature was normalized")

    #if not pubkey.ecdsa_verify(data, signature):
    if not pubkey.ecdsa_verify(data, normalized):
        print("verification failed", file=sys.stderr)
        sys.exit(1)
Ejemplo n.º 22
0
def getNUMS(index=0):
    """Taking secp256k1's G as a seed,
    either in compressed or uncompressed form,
    append "index" as a byte, and append a second byte "counter"
    try to create a new NUMS base point from the sha256 of that
    bytestring. Loop counter and alternate compressed/uncompressed
    until finding a valid curve point. The first such point is
    considered as "the" NUMS base point alternative for this index value.

    The search process is of course deterministic/repeatable, so
    it's fine to just store a list of all the correct values for
    each index, but for transparency left in code for initialization
    by any user.
    
    The NUMS generator generated is returned as a secp256k1.PublicKey.
    """

    assert index in range(256)
    nums_point = None
    for G in [getG(True), getG(False)]:
        seed = G + chr(index)
        for counter in range(256):
            seed_c = seed + chr(counter)
            hashed_seed = hashlib.sha256(seed_c).digest()
            #Every x-coord on the curve has two y-values, encoded
            #in compressed form with 02/03 parity byte. We just
            #choose the former.
            claimed_point = "\x02" + hashed_seed
            try:
                nums_point = secp256k1.PublicKey(claimed_point,
                                                 raw=True,
                                                 ctx=ctx)
                return nums_point
            except:
                continue
    assert False, "It seems inconceivable, doesn't it?"  # pragma: no cover
Ejemplo n.º 23
0
def decompress_raw(comp_type, raw, chomp=False):

    if comp_type == 0 or comp_type == 1:
        l = 20
    elif comp_type >= 2 and comp_type <= 5:
        l = 32
    else:
        l = comp_type - 6

    data = raw[:l]
    raw = raw[l:]

    if not chomp:
        assert len(raw) == 0

    if comp_type == 0:
        script = OP_DUP + OP_HASH160 + chr(20) + data + \
            OP_EQUALVERIFY + OP_CHECKSIG

    elif comp_type == 1:
        script = OP_HASH160 + chr(20) + data + OP_EQUAL

    elif comp_type == 2 or comp_type == 3:
        script = chr(33) + chr(comp_type) + data + OP_CHECKSIG

    elif comp_type == 4 or comp_type == 5:
        comp_pubkey = chr(comp_type - 2) + data
        pubkey = secp256k1.PublicKey(comp_pubkey,
                                     raw=True).serialize(compressed=False)

        script = chr(65) + pubkey + OP_CHECKSIG

    else:
        script = data

    return script, raw
Ejemplo n.º 24
0
import warnings

from sawtooth_signing.core import SigningError
from sawtooth_signing.core import ParseError

from sawtooth_signing.core import PrivateKey
from sawtooth_signing.core import PublicKey
from sawtooth_signing.core import Context

import secp256k1

import bitcoin as pybitcointools

__CONTEXTBASE__ = secp256k1.Base(ctx=None, flags=secp256k1.ALL_FLAGS)
__CTX__ = __CONTEXTBASE__.ctx
__PK__ = secp256k1.PublicKey(ctx=__CTX__)  # Cache object to use as factory


class Secp256k1PrivateKey(PrivateKey):
    def __init__(self, secp256k1_private_key):
        self._private_key = secp256k1_private_key

    def get_algorithm_name(self):
        return "secp256k1"

    def as_hex(self):
        return binascii.hexlify(self.as_bytes()).decode()

    def as_bytes(self):
        return bytes(self._private_key.private_key)
def lndecode(options):
    hrp, data = bech32_decode(options.lnaddress)
    if not hrp:
        sys.exit("Bad bech32 checksum")

    if not hrp.startswith('ln'):
        sys.exit("Does not start with ln")

    # Final signature takes 104 bytes (65 bytes base32 encoded)
    if len(data) < 103:
        sys.exit("Too short to contain signature")
    sigdecoded = convertbits(data[-104:], 5, 8, False)
    data = data[:-104]

    pubkey = secp256k1.PublicKey(flags=secp256k1.ALL_FLAGS)
    sig = pubkey.ecdsa_recoverable_deserialize(sigdecoded[0:64],
                                               sigdecoded[64])
    pubkey.public_key = pubkey.ecdsa_recover(
        bytearray([ord(c) for c in hrp] + data), sig)
    print("Signed with public key: {}".format(
        bytearray(pubkey.serialize()).hex()))

    m = re.search("[^\d]+", hrp[2:])
    currency = m.group(0)
    print("Currency: {}".format(currency))

    amountstr = hrp[2 + m.end():]
    if amountstr != '':
        # Postfix?
        if amountstr.endswith('p'):
            mul = 1
            amountstr = amountstr[:-1]
        elif amountstr.endswith('n'):
            mul = 10**3
            amountstr = amountstr[:-1]
        elif amountstr.endswith('u'):
            mul = 10**6
            amountstr = amountstr[:-1]
        elif amountstr.endswith('m'):
            mul = 10**9
            amountstr = amountstr[:-1]
        picobtc = int(amountstr) * mul
        print("Amount: {}".format(picobtc / 10**12))

        if options.rate:
            print("(Conversion: {})".format(picobtc / 10**12 *
                                            float(options.rate)))

    if len(data) < 7:
        sys.exit("Not long enough to contain timestamp")

    tstamp = from_u35(data[:7])
    data = data[7:]
    print("Timestamp: {} ({})".format(tstamp, time.ctime(tstamp)))

    while len(data) > 0:
        tag, tagdata, data = pull_tagged(data)
        if tag == 'r':
            tagdata = convertbits(tagdata, 5, 8, False)
            if len(tagdata) != 33 + 8 + 4 + 4:
                sys.exit('Unexpected r tag length {}'.format(len(tagdata)))
            print("Route: {}/{}/{}/{}".format(
                bytearray(tagdata[0:33]).hex(),
                bytearray(tagdata[33:41]).hex(), from_u32list(tagdata[41:45]),
                from_u32list(tagdata[45:49])))
        elif tag == 'f':
            if currency == 'bc' or currency == 'tb':
                wver = tagdata[0]
                if wver == 17:
                    addr = base58.b58encode_check(
                        bytes([base58_prefix_map[currency][0]] +
                              convertbits(tagdata[1:], 5, 8, False)))
                elif wver == 18:
                    addr = base58.b58encode_check(
                        bytes([base58_prefix_map[currency][1]] +
                              convertbits(tagdata[1:], 5, 8, False)))
                elif wver <= 16:
                    addr = bech32_encode(currency, tagdata)
                else:
                    sys.exit('Invalid witness version {}'.format(wver))

            # Other currencies here...
            else:
                addr = bytearray(tagdata).hex()
            print("Fallback: {}".format(addr))
        elif tag == 'd':
            tagdata = convertbits(tagdata, 5, 8, False)
            print("Description: {}".format(''.join(chr(c) for c in tagdata)))
        elif tag == 'h':
            tagdata = convertbits(tagdata, 5, 8, False)
            print("Description hash: {}".format(bytearray(tagdata).hex()))
        elif tag == 'x':
            print("Expiry (seconds): {}".format(from_5bit(tagdata)))
        elif tag == 'p':
            tagdata = convertbits(tagdata, 5, 8, False)
            assert len(tagdata) == 32
            print("Payment hash: {}".format(bytearray(tagdata).hex()))
        else:
            tagdata = convertbits(tagdata, 5, 8, False)
            print("UNKNOWN TAG {}: {}".format(tag, bytearray(tagdata).hex()))
Ejemplo n.º 26
0
 def from_bytes(byte_str):
     public_key = __PK__.deserialize(byte_str)
     return Secp256k1PublicKey(secp256k1.PublicKey(public_key, ctx=__CTX__))
Ejemplo n.º 27
0
def lndecode(a):
    hrp, data = bech32_decode(a)
    if not hrp:
        raise ValueError("Bad bech32 checksum")

    # BOLT #11:
    #
    # A reader MUST fail if it does not understand the `prefix`.
    if not hrp.startswith('ln'):
        raise ValueError("Does not start with ln")

    data = u5_to_bitarray(data)

    # Final signature 65 bytes, split it off.
    if len(data) < 65 * 8:
        raise ValueError("Too short to contain signature")
    sigdecoded = data[-65 * 8:].tobytes()
    data = bitstring.ConstBitStream(data[:-65 * 8])

    addr = LnAddr()
    addr.pubkey = None

    m = re.search("[^\d]+", hrp[2:])
    if m:
        addr.currency = m.group(0)
        amountstr = hrp[2 + m.end():]
        # BOLT #11:
        #
        # A reader SHOULD indicate if amount is unspecified, otherwise it MUST
        # multiply `amount` by the `multiplier` value (if any) to derive the
        # amount required for payment.
        if amountstr != '':
            addr.amount = unshorten_amount(amountstr)

    addr.date = data.read(35).uint

    while data.pos != data.len:
        tag, tagdata, data = pull_tagged(data)

        # BOLT #11:
        #
        # A reader MUST skip over unknown fields, an `f` field with unknown
        # `version`, or a `p`, `h`, `n` or `r` field which does not have
        # `data_length` 52, 52, 53 or 82 respectively.
        data_length = len(tagdata) / 5

        if tag == 'r':
            if data_length != 82:
                addr.unknown_tags.append((tag, tagdata))
                continue

            tagbytes = trim_to_bytes(tagdata)

            addr.tags.append(('r', (tagbytes[0:33], tagbytes[33:41],
                                    tagdata[41 * 8:49 * 8].intbe,
                                    tagdata[49 * 8:51 * 8].intbe)))
        elif tag == 'f':
            fallback = parse_fallback(tagdata, addr.currency)
            if fallback:
                addr.tags.append(('f', fallback))
            else:
                # Incorrect version.
                addr.unknown_tags.append((tag, tagdata))
                continue

        elif tag == 'd':
            addr.tags.append(('d', trim_to_bytes(tagdata).decode('utf-8')))

        elif tag == 'h':
            if data_length != 52:
                addr.unknown_tags.append((tag, tagdata))
                continue
            addr.tags.append(('h', trim_to_bytes(tagdata)))

        elif tag == 'x':
            addr.tags.append(('x', tagdata.uint))

        elif tag == 'p':
            if data_length != 52:
                addr.unknown_tags.append((tag, tagdata))
                continue
            addr.paymenthash = trim_to_bytes(tagdata)

        elif tag == 'n':
            if data_length != 53:
                addr.unknown_tags.append((tag, tagdata))
                continue
            addr.pubkey = secp256k1.PublicKey(flags=secp256k1.ALL_FLAGS)
            addr.pubkey.deserialize(trim_to_bytes(tagdata))

        elif tag == 'c':
            addr.min_final_cltv_expiry = tagdata.uint
        else:
            addr.unknown_tags.append((tag, tagdata))

    # BOLT #11:
    #
    # A reader MUST check that the `signature` is valid (see the `n` tagged
    # field specified below).
    if addr.pubkey:  # Specified by `n`
        # BOLT #11:
        #
        # A reader MUST use the `n` field to validate the signature instead of
        # performing signature recovery if a valid `n` field is provided.
        addr.signature = addr.pubkey.ecdsa_deserialize_compact(
            sigdecoded[0:64])
        if not addr.pubkey.ecdsa_verify(
                bytearray([ord(c)
                           for c in hrp]) + data.tobytes(), addr.signature):
            raise ValueError('Invalid signature')
    else:  # Recover pubkey from signature.
        addr.pubkey = secp256k1.PublicKey(flags=secp256k1.ALL_FLAGS)
        addr.signature = addr.pubkey.ecdsa_recoverable_deserialize(
            sigdecoded[0:64], sigdecoded[64])
        addr.pubkey.public_key = addr.pubkey.ecdsa_recover(
            bytearray([ord(c) for c in hrp]) + data.tobytes(), addr.signature)

    return addr
def podle_PublicKey(P):
    """Returns a PublicKey object from a binary string
    """
    return secp256k1.PublicKey(P, raw=True, ctx=ctx)
#!/usr/bin/python
from __future__ import print_function
import binascii
import hashlib
import re
import sys
import base64
import secp256k1

#Required only for PoDLE calculation:
N = 115792089237316195423570985008687907852837564279074904382605163141518161494337
#Global context for secp256k1 operations (helps with performance)
ctx = secp256k1.lib.secp256k1_context_create(secp256k1.ALL_FLAGS)
#required for point addition
dummy_pub = secp256k1.PublicKey(ctx=ctx)

#Standard prefix for Bitcoin message signing.
BITCOIN_MESSAGE_MAGIC = '\x18' + 'Bitcoin Signed Message:\n'

if sys.version_info.major == 2:
    string_types = (str, unicode)
    string_or_bytes_types = string_types
    int_types = (int, float, long)

    # Base switching
    code_strings = {
        2: '01',
        10: '0123456789',
        16: '0123456789abcdef',
        32: 'abcdefghijklmnopqrstuvwxyz234567',
        58: '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz',
Ejemplo n.º 30
0
def lndecode(a, verbose=False):
    hrp, data = bech32_decode(a)
    if not hrp:
        raise ValueError("Bad bech32 checksum")

    # BOLT #11:
    #
    # A reader MUST fail if it does not understand the `prefix`.
    if not hrp.startswith("ln"):
        raise ValueError("Does not start with ln")

    data = u5_to_bitarray(data)

    # Final signature 65 bytes, split it off.
    if len(data) < 65 * 8:
        raise ValueError("Too short to contain signature")
    sigdecoded = data[-65 * 8:].tobytes()
    data = bitstring.ConstBitStream(data[:-65 * 8])

    addr = LnAddr()
    addr.pubkey = None

    m = re.search("[^\d]+", hrp[2:])
    if m:
        addr.currency = m.group(0)
        amountstr = hrp[2 + m.end():]
        # BOLT #11:
        #
        # A reader SHOULD indicate if amount is unspecified, otherwise it MUST
        # multiply `amount` by the `multiplier` value (if any) to derive the
        # amount required for payment.
        if amountstr != "":
            addr.amount = unshorten_amount(amountstr)

    addr.date = data.read(35).uint

    while data.pos != data.len:
        tag, tagdata, data = pull_tagged(data)

        # BOLT #11:
        #
        # A reader MUST skip over unknown fields, an `f` field with unknown
        # `version`, or a `p`, `h`, or `n` field which does not have
        # `data_length` 52, 52, or 53 respectively.
        data_length = len(tagdata) / 5

        if tag == "r":
            # BOLT #11:
            #
            # * `r` (3): `data_length` variable.  One or more entries
            # containing extra routing information for a private route;
            # there may be more than one `r` field, too.
            #    * `pubkey` (264 bits)
            #    * `short_channel_id` (64 bits)
            #    * `feebase` (32 bits, big-endian)
            #    * `feerate` (32 bits, big-endian)
            #    * `cltv_expiry_delta` (16 bits, big-endian)
            route = []
            s = bitstring.ConstBitStream(tagdata)
            while s.pos + 264 + 64 + 32 + 32 + 16 < s.len:
                route.append((
                    s.read(264).tobytes(),
                    s.read(64).tobytes(),
                    s.read(32).intbe,
                    s.read(32).intbe,
                    s.read(16).intbe,
                ))
            addr.tags.append(("r", route))
        elif tag == "f":
            fallback = parse_fallback(tagdata, addr.currency)
            if fallback:
                addr.tags.append(("f", fallback))
            else:
                # Incorrect version.
                addr.unknown_tags.append((tag, tagdata))
                continue

        elif tag == "d":
            addr.tags.append(("d", trim_to_bytes(tagdata).decode("utf-8")))

        elif tag == "h":
            if data_length != 52:
                addr.unknown_tags.append((tag, tagdata))
                continue
            addr.tags.append(("h", trim_to_bytes(tagdata)))

        elif tag == "x":
            addr.tags.append(("x", tagdata.uint))

        elif tag == "p":
            if data_length != 52:
                addr.unknown_tags.append((tag, tagdata))
                continue
            addr.paymenthash = trim_to_bytes(tagdata)

        elif tag == "n":
            if data_length != 53:
                addr.unknown_tags.append((tag, tagdata))
                continue
            addr.pubkey = secp256k1.PublicKey(flags=secp256k1.ALL_FLAGS)
            addr.pubkey.deserialize(trim_to_bytes(tagdata))
        else:
            addr.unknown_tags.append((tag, tagdata))

    if verbose:
        print("hex of signature data (32 byte r, 32 byte s): {}".format(
            hexlify(sigdecoded[0:64])))
        print("recovery flag: {}".format(sigdecoded[64]))
        print("hex of data for signing: {}".format(
            hexlify(bytearray([ord(c) for c in hrp]) + data.tobytes())))
        print("SHA256 of above: {}".format(
            hashlib.sha256(bytearray([ord(c) for c in hrp]) +
                           data.tobytes()).hexdigest()))

    # BOLT #11:
    #
    # A reader MUST check that the `signature` is valid (see the `n` tagged
    # field specified below).
    if addr.pubkey:  # Specified by `n`
        # BOLT #11:
        #
        # A reader MUST use the `n` field to validate the signature instead of
        # performing signature recovery if a valid `n` field is provided.
        addr.signature = addr.pubkey.ecdsa_deserialize_compact(
            sigdecoded[0:64])
        if not addr.pubkey.ecdsa_verify(
                bytearray([ord(c)
                           for c in hrp]) + data.tobytes(), addr.signature):
            raise ValueError("Invalid signature")
    else:  # Recover pubkey from signature.
        addr.pubkey = secp256k1.PublicKey(flags=secp256k1.ALL_FLAGS)
        addr.signature = addr.pubkey.ecdsa_recoverable_deserialize(
            sigdecoded[0:64], sigdecoded[64])
        addr.pubkey.public_key = addr.pubkey.ecdsa_recover(
            bytearray([ord(c) for c in hrp]) + data.tobytes(), addr.signature)

    return addr