Author

Topic: Pubkey recovery from ECDSA signature (getting owner's public key from its tx) (Read 529 times)

legendary
Activity: 3472
Merit: 10611
I just want to ask if the script to recover privatekey from the wallet that exposes its public key works which are we all in danger to lose our BTC because of doing a transaction?
It is impossible to recover a private key from public key and the operation is so expensive that it probably won't be solved in our lifetime.

Quote
I understand why there is the need for using fresh BTC address every transaction to avoid publishing publickey. But seems a very weak security if this is the case.
It is better to not-reuse addresses for many reasons involving privacy but you should know that if it were possible to compute private key from public key, bitcoin would become worthless and it won't matter if you didn't reuse addresses.!
hero member
Activity: 3038
Merit: 617

anyway the real script i should have shared is https://github.com/tintinweb/ecdsa-private-key-recovery

edit: the script could run for half hour strait but maybe crash, bcinfo don't limit as they say nxt time plz don't skim but test

So much information here I didn't even thought that every digits in public key has significant information corresponding to some data. I just want to ask if the script to recover privatekey from the wallet that exposes its public key works which are we all in danger to lose our BTC because of doing a transaction?
I understand why there is the need for using fresh BTC address every transaction to avoid publishing publickey. But seems a very weak security if this is the case.
sr. member
Activity: 356
Merit: 268
i modified this to work with python3

its not perfect, just past bitcoin address after launching it (name it r.py )

on console do python3 r.py
and enter the bitcoin address, preferably one with nonce reuse known so you see if its vulnerable

--snip--

I skimmed the code and there are few things i'd like to mention,
1. blockchain.info now is blockchain.com
2. blockchain.com ask you to limit queries to 1 query/10 seconds. They might block if the script is too fast.

Please limit your queries to a maximum of 1 every 10 seconds.

I hate blockchain.com/info but do you think i would post something without checking? well i probably do as i forgot to mention it's for python27,

i edited a line so it worked without breaking i forgot which one it was

Code:
#!/usr/bin/python

#################################################################################
#                                                                               #
#.______               _______.  ______     ___      .__   __.                  #
#|   _  \             /       | /      |   /   \     |  \ |  |                  #
#|  |_)  |    ______ |   (----`|  ,----'  /  ^  \    |   \|  |                  #
#|      /    |______| \   \    |  |      /  /_\  \   |  . `  |                  #
#|  |\  \----.    .----)   |   |  `----./  _____  \  |  |\   |                  #
#| _| `._____|    |_______/     \______/__/     \__\ |__| \__|  v0.2.0          #
#                                                                               #
#GNU PL - 2015 - ca333  (modified by simcity4242)                                                           #
#                                                                               #
#USE AT OWN RISK!                                                               #
#################################################################################

import json
import urllib2
import time
import sys

#for some reason blockchain.info api-chain is 59711 blocks short..
#blockstart = 170399
#blockstart += 59711
#blockcount = urllib2.urlopen("https://blockchain.info/en/q/getblockcount").read()

def rscan(addr):
        """Check address for duplicated r values."""
        # TODO: add BCI API check address

        print "WELCOME TO R-scan v0.1.2!"
        print "ADDRESS-R-SCAN: "

        urladdr = 'https://blockchain.info/address/%s?format=json&offset=%s'

        ###control api-url
        #print str(urladdr[:-22] % addr)

        addrdata = json.load(urllib2.urlopen(urladdr % (addr, '0')))
        ntx = addrdata['n_tx']
        print "Data for pubkey: " + str(addr) + " has " + str(addrdata['n_tx']).center(6) + "Tx%s" % 's'[ntx==1:]
        #print "number of txs: " + str(addrdata['n_tx'])

        #tx-details:

        txs = []
        for i in range(0, ntx//50 + 1):
                sys.stderr.write("Fetching Txs from offset\t%s\n" % str(i*50))
                jdata = json.load(urllib2.urlopen(urladdr % (addr, str(i*50))))
                txs.extend(jdata['txs'])

        #assert len(txs) == ntx
        addrdata['txs'] = txs


        y = 0
        inputs = []
        while y < ntx:
                #print "#################################################################################"
                #print "TX nr :" + str(y+1)
                #print "hash: " + str(addrdata['txs'][y]['hash'])
                #print "number of inputs: " + str(addrdata['txs'][y]['vin_sz'])
                #only if
                        #if addrdata['txs'][y]['vin_sz'] > 1:
                zy = 0
                while zy < addrdata['txs'][y]['vin_sz']:
                        print "Input-ScriptNR " + str(zy+1) + " :" + str(addrdata['txs'][y]['inputs'][zy]['script'])
                        inputs.append(addrdata['txs'][y]['inputs'][zy]['script'])
                        zy += 1
                y += 1

        xi = 0
        zi = 1
        lenx = len(inputs)
        alert = 0

        bad = []
        #compare the sig values in each input script
        while xi < lenx-1:
                x = 0
                while x < lenx-zi:
                        if inputs[xi][10:74] == inputs[x+zi][10:74]:
                                print "In Input NR: " + str(xi) + "[global increment] " + str(inputs[xi])
                                print('\a')
                                print "Resued R-Value: "
                                print inputs[x+zi]
                                bad.append((int(x), str(inputs[x+zi][10:74])))
                                alert += 1
                        x += 1
                        zi += 1
                xi += 1

        #check duplicates
        #alert when everything ok

        if alert < 1:
                print "Good pubKey. No problems."
        else:
                print "Address %s has %d reused R value%s!" % (addr, len(bad), "s"[len(bad)==1:])
                return bad

if __name__ == '__main__':
        from sys import argv
        print """python rscan.py 1BFhrfTTZP3Nw4BNy4eX4KFLsn9ZeijcMm"""
        if len(argv) == 1:
                addr = raw_input("Enter Bitcoin address eg 1BFhrfTTZP3Nw4BNy4eX4KFLsn9ZeijcMm")
        elif len(argv) == 2 and isinstance(argv[1], basestring):
                addr = str(argv[1])
        rscan(addr)

# 9ec4bc49e828d924af1d1029cacf709431abbde46d59554b62bc270e3b29c4b1


Quote
Data for pubkey: 1C8x2hqqgE2b3TZPQcFgas73xYWNh6TK9W has   8   Txs
Fetching Txs from offset        0
Input-ScriptNR 1 :48304502200f18c2d1fe6513b90f44513e975e05cc498e7f5a565b46c65b1d448734392c6f02210 0f80dee18431a82bfbbede36fe455cbd63158bd2c118ed36772a18da213db51ec014104d0fe07ff 74c9ef5b00fed1104fad43ecf72dbab9e60733e4f56eacf24b20cf3b8cd945bcabcc73ba0158bf9 ce769d43e94bd58c5c7e331a188922b3fe9ca1f5a
Input-ScriptNR 1 :48304502202b83d59c1d23c08efd82ee0662fec23309c3adbcbd1f0b8695378db4b14e736602210 0933bd8673a9ef8289a66305a5d86b11e93eace454220cdddd45ddfab4d6b27d4014104d0fe07ff 74c9ef5b00fed1104fad43ecf72dbab9e60733e4f56eacf24b20cf3b8cd945bcabcc73ba0158bf9 ce769d43e94bd58c5c7e331a188922b3fe9ca1f5a
Input-ScriptNR 1 :4b3048022200002b83d59c1d23c08efd82ee0662fec23309c3adbcbd1f0b8695378db4b14e73660 2220000334a96676e58b1bb01784cb7c556dd8ce1c220171904da22e18fe1e7d1510db5014104d0 fe07ff74c9ef5b00fed1104fad43ecf72dbab9e60733e4f56eacf24b20cf3b8cd945bcabcc73ba0 158bf9ce769d43e94bd58c5c7e331a188922b3fe9ca1f5a
Input-ScriptNR 1 :483045022100e9507a191ea86c8e689377130a1c775637d54184168a5b74cdb3c63018006be3022 062dba5c682e2413f2ae5461348dd7421b46f74e76d33ef0390fa7ec069dd8c07014104d0fe07ff 74c9ef5b00fed1104fad43ecf72dbab9e60733e4f56eacf24b20cf3b8cd945bcabcc73ba0158bf9 ce769d43e94bd58c5c7e331a188922b3fe9ca1f5a
Input-ScriptNR 1 :483045022100e2f79235bd4ef09ee56737422ad6b2f224d9bbfd5654738946fa7721860a56b0022 00936e3dbe07340f74ebafd39e1166c1c4b777b5e48a234939050bc9bb9f10a0e014104d0fe07ff 74c9ef5b00fed1104fad43ecf72dbab9e60733e4f56eacf24b20cf3b8cd945bcabcc73ba0158bf9 ce769d43e94bd58c5c7e331a188922b3fe9ca1f5a
Input-ScriptNR 1 :483045022100c81a4ec35697dfdf3fd21e6ed2a654d6d9a62ddc96494838f10f66c8c25f679e022 00e76db47b8463877971d1324f644c65c7ad5a44993db7b9e75a43d2978b6d045014104d0fe07ff 74c9ef5b00fed1104fad43ecf72dbab9e60733e4f56eacf24b20cf3b8cd945bcabcc73ba0158bf9 ce769d43e94bd58c5c7e331a188922b3fe9ca1f5a
Input-ScriptNR 1 :48304502200f18c2d1fe6513b90f44513e975e05cc498e7f5a565b46c65b1d448734392c6f02210 0b29a06f2e30064542b298d711c315dca9ca99756180219699f776dd3d6a6bbc90141049ba39856 eec011b79f1acb997760ed9d3f90d477077d17df2571d94b2fa2137bf0976d786b6aabc903746e2 69628b2c28e4b5db753845e5713a48ee7d6b97aaf
Input-ScriptNR 2 :48304502202b83d59c1d23c08efd82ee0662fec23309c3adbcbd1f0b8695378db4b14e736602210 0d66567fbfc4bb78520883d599bc51585f75393d2e6b227997410331e09fce5ae0141049ba39856 eec011b79f1acb997760ed9d3f90d477077d17df2571d94b2fa2137bf0976d786b6aabc903746e2 69628b2c28e4b5db753845e5713a48ee7d6b97aaf
Input-ScriptNR 1 :48304502200f18c2d1fe6513b90f44513e975e05cc498e7f5a565b46c65b1d448734392c6f02210 0917766d14f2e9933eb269c83b3ad440ed8432da8beb5733f34046509e48b1d850141049ba39856 eec011b79f1acb997760ed9d3f90d477077d17df2571d94b2fa2137bf0976d786b6aabc903746e2 69628b2c28e4b5db753845e5713a48ee7d6b97aaf
In Input NR: 1[global increment] 48304502202b83d59c1d23c08efd82ee0662fec23309c3adbcbd1f0b8695378db4b14e736602210 0933bd8673a9ef8289a66305a5d86b11e93eace454220cdddd45ddfab4d6b27d4014104d0fe07ff 74c9ef5b00fed1104fad43ecf72dbab9e60733e4f56eacf24b20cf3b8cd945bcabcc73ba0158bf9 ce769d43e94bd58c5c7e331a188922b3fe9ca1f5a

Resued R-Value:
48304502202b83d59c1d23c08efd82ee0662fec23309c3adbcbd1f0b8695378db4b14e736602210 0d66567fbfc4bb78520883d599bc51585f75393d2e6b227997410331e09fce5ae0141049ba39856 eec011b79f1acb997760ed9d3f90d477077d17df2571d94b2fa2137bf0976d786b6aabc903746e2 69628b2c28e4b5db753845e5713a48ee7d6b97aaf
Address 1C8x2hqqgE2b3TZPQcFgas73xYWNh6TK9W has 1 reused R value!
root@localhost:~/rsz#

anyway the real script i should have shared is https://github.com/tintinweb/ecdsa-private-key-recovery

edit: the script could run for half hour strait but maybe crash, bcinfo don't limit as they say nxt time plz don't skim but test
sr. member
Activity: 356
Merit: 268
i modified this to work with python3

its not perfect, just past bitcoin address after launching it (name it r.py )

on console do python3 r.py
and enter the bitcoin address, preferably one with nonce reuse known so you see if its vulnerable

Code:
#!/usr/bin/python

#################################################################################
#                                                                               #
#.______               _______.  ______     ___      .__   __.                  #
#|   _  \             /       | /      |   /   \     |  \ |  |                  #
#|  |_)  |    ______ |   (----`|  ,----'  /  ^  \    |   \|  |                  #
#|      /    |______| \   \    |  |      /  /_\  \   |  . `  |                  #
#|  |\  \----.    .----)   |   |  `----./  _____  \  |  |\   |                  #
#| _| `._____|    |_______/     \______/__/     \__\ |__| \__|  v0.2.0          #
#                                                                               #
#GNU PL - 2015 - ca333  (modified by simcity4242)     #
#                                                                               #
#USE AT OWN RISK!                                                               #
#################################################################################

import json
import urllib2
import time
import sys

#for some reason blockchain.info api-chain is 59711 blocks short..
#blockstart = 170399
#blockstart += 59711
#blockcount = urllib2.urlopen("https://blockchain.info/en/q/getblockcount").read()

def rscan(addr):
"""Check address for duplicated r values."""
# TODO: add BCI API check address

print "WELCOME TO R-scan v0.1.2!"
print "ADDRESS-R-SCAN: "

urladdr = 'https://blockchain.info/address/%s?format=json&offset=%s'

###control api-url
#print str(urladdr[:-22] % addr)

addrdata = json.load(urllib2.urlopen(urladdr % (addr, '0')))
ntx = addrdata['n_tx']
print "Data for pubkey: " + str(addr) + " has " + str(addrdata['n_tx']).center(6) + "Tx%s" % 's'[ntx==1:]
#print "number of txs: " + str(addrdata['n_tx'])

#tx-details:

txs = []
for i in range(0, ntx//50 + 1):
sys.stderr.write("Fetching Txs from offset\t%s\n" % str(i*50))
jdata = json.load(urllib2.urlopen(urladdr % (addr, str(i*50))))
txs.extend(jdata['txs'])

#assert len(txs) == ntx
addrdata['txs'] = txs


y = 0
inputs = []
while y < ntx:
#print "#################################################################################"
#print "TX nr :" + str(y+1)
#print "hash: " + str(addrdata['txs'][y]['hash'])
#print "number of inputs: " + str(addrdata['txs'][y]['vin_sz'])
#only if
#if addrdata['txs'][y]['vin_sz'] > 1:
zy = 0
while zy < addrdata['txs'][y]['vin_sz']:
print "Input-ScriptNR " + str(zy+1) + " :" + str(addrdata['txs'][y]['inputs'][zy]['script'])
inputs.append(addrdata['txs'][y]['inputs'][zy]['script'])
zy += 1
y += 1

xi = 0
zi = 1
lenx = len(inputs)
alert = 0

bad = []
#compare the sig values in each input script
while xi < lenx-1:
x = 0
while x < lenx-zi:
if inputs[xi][10:74] == inputs[x+zi][10:74]:
print "In Input NR: " + str(xi) + "[global increment] " + str(inputs[xi])
print('\a')
print "Resued R-Value: "
print inputs[x+zi]
bad.append((int(x), str(inputs[x+zi][10:74])))
alert += 1
x += 1
zi += 1
xi += 1

#check duplicates
#alert when everything ok

if alert < 1:
print "Good pubKey. No problems."
else:
print "Address %s has %d reused R value%s!" % (addr, len(bad), "s"[len(bad)==1:])
return bad

if __name__ == '__main__':
from sys import argv
print """python rscan.py 1BFhrfTTZP3Nw4BNy4eX4KFLsn9ZeijcMm"""
if len(argv) == 1:
addr = raw_input("Enter Bitcoin address eg 1BFhrfTTZP3Nw4BNy4eX4KFLsn9ZeijcMm")
elif len(argv) == 2 and isinstance(argv[1], basestring):
addr = str(argv[1])
rscan(addr)

# 9ec4bc49e828d924af1d1029cacf709431abbde46d59554b62bc270e3b29c4b1
newbie
Activity: 10
Merit: 15
Bump! Sorry if it's too soon to do a bump, also I edited my above reply.

I have another question, it's only to confirm I understood the process.

I read the following stackexchange posts:

- https://bitcoin.stackexchange.com/questions/8250/what-is-relation-between-scriptsig-and-scriptpubkey
- https://bitcoin.stackexchange.com/questions/93966/getting-public-key-from-any-raw-transaction-what-to-take-care-of
- https://bitcoin.stackexchange.com/questions/8235/how-is-the-output-script-formed
- https://bitcoin.stackexchange.com/questions/91088/how-do-i-get-the-scriptpubkey-type-from-the-raw-output-script
- https://bitcoin.stackexchange.com/questions/100907/retrieving-an-addresses-public-key-from-pkscript-sigscript-witness

So, if I understand correctly when you generate a transaction, then you have a sender (input) and receiver (output). When everything is signed and sent into the blockchain, two things happen,

the sender (input) sends this into the blockchain (created by its wallet client):

Code:
scriptPubKey = OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG

and the receiver (output):

Code:
scriptSig =

Everything right until here? (correct me please)

Then, if I would like to retrieve the public key I must define what it's going on here and which options do I have left.

I'd like to have as many public keys as possible.

To clarify things,

to crawl pubkey from the sender (input) then I'll need to look into the signature on the scriptSig part of the receiver (output), and try to decode it?

to crawl pubkey from the receiver (output) then I'll need to look into the type of script as @pooya87 stated here:

When spending a P2PKH output, the public key is the top stack element when reaching OP_CHECKSIG.
When spending a P2WPKH output, the public key is the second witness item.
When spending a P2PK output, the public key is in the output.
When spending a P2TR output, the public key is a tweaked pubkey in the output (the witness program).
When spending other scripts such as P2SH when you reach any of the above op codes it should be the top stack element or in case of multi signatures there are multiple pubkeys.

So, Idk if I'm missing something more, I think that's the only way to get the public keys on both cases.

There are some made examples that are useful:

- https://github.com/bitcoin-core/btcdeb#script-compiler

Code:
> btcc OP_DUP OP_HASH160 897c81ac37ae36f7bc5b91356cfb0138bfacb3c1 OP_EQUALVERIFY OP_CHECKSIG
> 76a914897c81ac37ae36f7bc5b91356cfb0138bfacb3c188ac

But the hash generated here is not a public key?

And also I saw a php implementation for a rpc client for btc node, and a very interesting issue:

- https://github.com/Bit-Wasp/bitcoin-p2p-php/issues/29

Code:
$db = new PDO('pgsql:dbname=explore;host=localhost;','pgsql','');
$count = $rpc->getblockcount();
for ($i=0;$i<=$count;$i++) {

    $hash = $rpc->getblock($rpc->getblockhash($i));
    foreach ($hash['tx'] as $tx) {
        $raw = $rpc->getrawtransaction($tx);
        if ($raw == -5) {
            continue;
        } else {
            $x = $rpc->decoderawtransaction($raw);
            if(is_array($x)) {
                foreach ($x['vin'] as $vin) {
                    if (isset($vin['coinbase']))
                        continue;
                    $txid = $vin['txid'];
                    $stmt = $db->prepare('delete from tx where txid = :id');
                    $stmt->bindValue('id',$x['txid']);
                    $stmt->execute();
                }
                foreach ($x['vout'] as $index=>$out) {var_dump($out['value']);
                    $stmt = $db->prepare('insert into tx (txid,"value",n,pubkey,address) values (:id,:value,:n,:pubkey,:address)');
                    $stmt->bindValue(':id',$x['txid']);
                    $stmt->bindValue(':value',$out['value']);
                    $stmt->bindValue(':n',$index);
                    $stmt->bindValue(':pubkey',$out['scriptPubKey']['hex']);
                    $stmt->bindValue(':address',$out['scriptPubKey']['addresses'][0]);
                    $stmt->execute();
                }
            }
        }
    }
}

So,

Code:
                   $stmt->bindValue(':pubkey',$out['scriptPubKey']['hex']);
                    $stmt->bindValue(':address',$out['scriptPubKey']['addresses'][0]);

- :pubkey is the hash
- :address is the public key (I need to research this)?


More questions,

- so the easy way is to have the sender (input) pubkey?
- because, the receiver (output) must have to recover the public key from it's signature which is a expensive process for a lot of addreses?
- we have 720M of transactions, txid (right?)? https://www.blockchain.com/charts/n-transactions-total if I list txid I can still use btcc to have pubkey (I think not)?
- having bitcoin core rpc calls: https://developer.bitcoin.org/reference/rpc/index.html which has listunspent that does something similar to btcposbal2csv (as I understood)?
- but isn't there any rpc call to retrieve public keys from an txid? (EDIT: well, I saw this: https://gist.github.com/t4sk/68dbde1ef75762753214c0b3823097e8 and on documentation you can see: https://developer.bitcoin.org/reference/rpc/validateaddress.html but I don't know if it will work)
- and last, even if I have the pubkey from the sender/receiver I must check the balance if it's positive?

From the last question, I have some premises that Idk if they are right:

Most of the public keys exposed:

- have a high bit range (above 120 bits)
- the ones left with lower bit range are all spent/cracked (their corresponding btc address has a 0 BTC balance)
newbie
Activity: 10
Merit: 15
Thanks for your response,

I have done some research, this repositories has interesting methods:

- https://github.com/bitcoin-core/btcdeb/blob/master/doc/btcdeb.md
- https://github.com/yogh-io/bitcoin-transaction-explorer (in Java)

But the one that I think is the best, is this: https://github.com/Bit-Wasp/bitcoin-p2p-php/issues/29 (the problem is that the code has changed a lot since 2015, so I'll be researching on this).

It can run on top of the bitcoind, so I can be interesting because I don't need to stop it.
legendary
Activity: 2268
Merit: 18711
But I would like to ask, recovering the pubkey from its signature it's really expensive process or not?
Not hugely for a handful of addresses. You need to hash the message if you don’t already have the hash, calculate the multiplicative inverse of r, and some elliptic curve multiplication, but the rest is pretty trivial. Different if you want to do it for millions of messages/signatures. You would only need to do this to recover the public key from a signed message which was not a transaction though, since with transactions the public key is revealed anyway.

I mean that the only addresses that have money are utxos with a positive balance, everything else isn't worth it.
The only addresses which have money are addresses which contain unspent UTXOs. You can't deduct part of a balance from a UTXO like you can with an address. You either spend the entire UTXO or you spend none of it.
newbie
Activity: 10
Merit: 15
What do you mean duplicates? Addresses that have spent once and still have a balance?

Addresses that are duplicated on the list. But I edited my last post, all the addresses I crawled are not duped because the program was storing all addrs in a map.

Perhaps you're using Google Translate as this neither makes sense.

No, I don't.
legendary
Activity: 1512
Merit: 7340
Farewell, Leo
But I would like to ask, recovering the pubkey from its signature it's really expensive process or not?
It's considered expensive, but it's not going to take lots of computational effort. See: [Questions] Public key cost comparison.

Then, I¡ll need to find duplicates.
What do you mean duplicates? Addresses that have spent once and still have a balance?

Well, I'm just a newbie trying to learn. Implementing this thing will require much more knowledge, so you can be relaxed!
Perhaps you're using Google Translate as this neither makes sense.
newbie
Activity: 10
Merit: 15
That's not how you recover public keys from signature and message [hash]!
It's actually a simple process of computing Q = r−1(sR − eG) for R and -R.

So is the Kangroo project the reason why you are looking for public keys? Are you trying to recover "private" key of other people by having their public key?!!

Yes, I know that's not the way to recover public keys. But I would like to ask, recovering the pubkey from its signature it's really expensive process or not?



Of course. There is no limit to how many UTXOs can be sent to a single address.

Then, I'll need to find duplicates.
EDIT: No, this py program I shared already does that, so isn't neccesary.

You'll need to clarify what you are asking here since this doesn't make sense.

I mean that the only addresses that have money are utxos with a positive balance, everything else isn't worth it.

Certainly looks like that. And here I just thought it was an interested newbie trying to learn. Sad

Well, I'm just a newbie trying to learn. Implementing this thing will require much more knowledge, so you can be relaxed!

Anyways, thanks to both, because nnow I understand blockchain clearly.
legendary
Activity: 2268
Merit: 18711
But then, this program has something I don't trust on, can two utxo point to the same address?
Of course. There is no limit to how many UTXOs can be sent to a single address.

And also, I'm feeling like if missing something, like addresses that aren't pointing to any real address
You'll need to clarify what you are asking here since this doesn't make sense.

Are you trying to recover "private" key of other people by having their public key?!!
Certainly looks like that. And here I just thought it was an interested newbie trying to learn. Sad
legendary
Activity: 3472
Merit: 10611
Thanks. I think that by the moment I'm not interested in doing I have Kangaroo implementation of Jean-Luc Pons.
That's not how you recover public keys from signature and message [hash]!
It's actually a simple process of computing Q = r−1(sR − eG) for R and -R.

So is the Kangroo project the reason why you are looking for public keys? Are you trying to recover "private" key of other people by having their public key?!!
newbie
Activity: 10
Merit: 15
Note that recovering a public key from an ECDSA signature, alone, is impossible. To compute the public key (without knowing it from the transaction data) you need to know the values r, s and z, where (r, s) represents the signature and z the hash of the message you want to sign.

Also note that recovering a public key from r, s and z is a different (more computationally expensive) procedure than to recover it from the transaction data. When you sign a transaction, you include your signature with your public key.

Thanks. I think that by the moment I'm not interested in doing I have Kangaroo implementation of Jean-Luc Pons.



So you mean that explorer shows everything but real balance are the utxo. Then we can assume that this address I share it has 17BTC?
Correct. The balance of addresses really only exists to make things easier for us to interpret. The protocol deals with individual UTXOs.

Thanks for the API, but to clarify I want to implement it by myself, so I cannot abuse an API for this task. Anything guidance here is welcome!
So let's take the address you linked to, and then look at the transaction where it spends coins: https://mempool.space/tx/4d5cfc3a5d8d81e64235d527ad0521fd92fdaa7e8bf65d73421d5bc999f9b30c

Hit the button titled "Details", and then let's look at the scriptsig (in hex) for any of the inputs (the scriptsig is the same for all three inputs since all three inputs come from the same address):
Code:
47304402207965f47d583936d18267c1a207f5b7884c9dff5ab6b2cda644d078a9692aecd702204f08a3cb3529189e1967bdbdec88cc07a8baf19f0aee777224a37d39c39d0eff0141044188e7b878d0d88872ba579b8bbdb05161d985f4063d520e751340a6ec50d9f62544911e4b2ff1de589e452b7cfd0f786fd58fcdf5ecf80b6405304db173bba5

So let's break this down and see what it is telling us.

47Push 71 bytes
30Header byte indicating signature
44Length of what follows (68 bytes)
02Header byte for R
20Length of R (32 bytes)
7965.....ecd7R
02Header byte for S
20Length of S (32 bytes)
4f08.....0effS
01Hashtype byte (SIGHASH_ALL)
------------------------------------------------------------------------
41Push 65 bytes
0441....bba5Pubkey

However, this is just one example for a legacy P2PKH UTXO. Even other P2PKH UTXOs could be a little different as the length of every element is not necessarily fixed, and if the UTXO is of a different format, such as segwit or taproot, then it will be completely different altogether.

Thanks for your guidance! Now I have a little bit clearer approach.

Then: https://github.com/graymauser/btcposbal2csv this is correct, I need first utxo that are have the addresses with outputs (so that money can still be spent).

But also, inherent to the extracted addresses we can look if it has spent outputs (it has sent money) and then look for its public key depending on the address type.

But then, this program has something I don't trust on, can two utxo point to the same address? Maybe I'll need to search for duplicates.

And also, I'm feeling like if missing something, like addresses that aren't pointing to any real address, but maybre I'm wrong. I'll like to extract as much as addresses with spendable money as I can and I onoy have like 31M.

But blocksci is powerful, but unmaintained and complex to understand so, Idk what to do more.

Also, this page: http://alladdresses.loyce.club/ gives me a clue that there are more addresses, but every address that existed doesn't mean that has it can be spent or even have balance.
legendary
Activity: 2268
Merit: 18711
So you mean that explorer shows everything but real balance are the utxo. Then we can assume that this address I share it has 17BTC?
Correct. The balance of addresses really only exists to make things easier for us to interpret. The protocol deals with individual UTXOs.

Thanks for the API, but to clarify I want to implement it by myself, so I cannot abuse an API for this task. Anything guidance here is welcome!
So let's take the address you linked to, and then look at the transaction where it spends coins: https://mempool.space/tx/4d5cfc3a5d8d81e64235d527ad0521fd92fdaa7e8bf65d73421d5bc999f9b30c

Hit the button titled "Details", and then let's look at the scriptsig (in hex) for any of the inputs (the scriptsig is the same for all three inputs since all three inputs come from the same address):
Code:
47304402207965f47d583936d18267c1a207f5b7884c9dff5ab6b2cda644d078a9692aecd702204f08a3cb3529189e1967bdbdec88cc07a8baf19f0aee777224a37d39c39d0eff0141044188e7b878d0d88872ba579b8bbdb05161d985f4063d520e751340a6ec50d9f62544911e4b2ff1de589e452b7cfd0f786fd58fcdf5ecf80b6405304db173bba5

So let's break this down and see what it is telling us.

47Push 71 bytes
30Header byte indicating signature
44Length of what follows (68 bytes)
02Header byte for R
20Length of R (32 bytes)
7965.....ecd7R
02Header byte for S
20Length of S (32 bytes)
4f08.....0effS
01Hashtype byte (SIGHASH_ALL)
------------------------------------------------------------------------
41Push 65 bytes
0441....bba5Pubkey

However, this is just one example for a legacy P2PKH UTXO. Even other P2PKH UTXOs could be a little different as the length of every element is not necessarily fixed, and if the UTXO is of a different format, such as segwit or taproot, then it will be completely different altogether.
legendary
Activity: 1512
Merit: 7340
Farewell, Leo
Note that recovering a public key from an ECDSA signature, alone, is impossible. To compute the public key (without knowing it from the transaction data) you need to know the values r, s and z, where (r, s) represents the signature and z the hash of the message you want to sign.

Also note that recovering a public key from r, s and z is a different (more computationally expensive) procedure than to recover it from the transaction data. When you sign a transaction, you include your signature with your public key.
newbie
Activity: 10
Merit: 15
Bitcoin is not using a balance-based ledger, it is using an output based ledger. Meaning you only have UTXOs at protocol level and only the wallet or block explorers show "balance" for convenience.

So you mean that explorer shows everything but real balance are the utxo. Then we can assume that this address I share it has 17BTC?

Hello
api  blockchain.info/q/pubkeyaddr/18yGdLieoWDBrkfFcU6mSJJzNMMfRztDUg
Also you can extract public x,y from R,S,Z method is "Y = (R*s-G*m)/r"


Thanks for the API, but to clarify I want to implement it by myself, so I cannot abuse an API for this task. Anything guidance here is welcome!
member
Activity: 69
Merit: 53
Hello
api  blockchain.info/q/pubkeyaddr/18yGdLieoWDBrkfFcU6mSJJzNMMfRztDUg
Also you can extract public x,y from R,S,Z if its made output transaction.
Math is "Y = (R*s-G*m)/r"
legendary
Activity: 3472
Merit: 10611
So, if every 2,016 blocks the difficulty increases (I think it doubles), there are 21,000,000/2,016=972.2222 (bits?) of difficulty.
And each difficulty has 12,600 BTC. Interesting.
Every 2016 blocks the difficulty adjusts so that it takes 2 weeks to mine 2016 blocks. It may go down or up based on how long it took to mine previous 2016 blocks.
The reward for blocks remains the same for 210,000 blocks (about 4 years) and after each 210,000 block the reward is reduces by 50% (cut in half).

Quote
Then, you mean that all future tx done by anyone within that block their fees are returned back to the miner that found that block?
Not exactly returned back. When the miner wants to start the work they first construct the block. The steps is including as many transactions in that block as they can until its weight reaches 4000000 units. Then they update the block header (merkle root hash) and the first transaction in that block known as coinbase transaction by updating its output amount to be block reward + sum of fees of all transactions in that block.
Then they start mining it and if they find the correct hash they publish the whole block for the rest of the network to sync.

Quote
Why do you say it's irrelevant, I didn't understand, sorry.
Bitcoin is not using a balance-based ledger, it is using an output based ledger. Meaning you only have UTXOs at protocol level and only the wallet or block explorers show "balance" for convenience.

Quote
And how did you recovered it? I'd like to learn this.
You simply take any of the outgoing transactions and decode them to get the public key which is located in signature script or inside the witness depending on the output type they are spending.
I think blockchain.com has an API for it too where you entered the address and it gave you the public key if it could but I can't find it anymore.
newbie
Activity: 10
Merit: 15
The coinbase transaction is the first transaction in each block in which the miner who found that block sends the block reward of (currently) 6.25 BTC brand new bitcoin to themselves, along with the transaction fees collected from all the transactions within that block they just found.

So, if every 2,016 blocks the difficulty increases (I think it doubles), there are 21,000,000/2,016=972.2222 (bits?) of difficulty.
And each difficulty has 12,600 BTC. Interesting.

Also, you mentioned: "along with the transaction fees collected from all the transactions within that block they just found".

Then, you mean that all future tx done by anyone within that block their fees are returned back to the miner that found that block?

Absolutely. If I send two outputs of 1 BTC each to an address, and then spend one of those bitcoin, the address will have used up an output and will still have a balance of 1 BTC.

Yes, I see two world icons on the blockchain page. The one in red is the 3BTC tx that was spent so the balance is taken from the full one (20-3=17BTC).

Yes. To make any transaction the pubkey is exposed. The remaining balance on the address (or lack thereof) is irrelevant.

Why do you say it's irrelevant, I didn't understand, sorry.

For the address you have linked, the public key is in uncompressed format and is as follows:
Code:
044188e7b878d0d88872ba579b8bbdb05161d985f4063d520e751340a6ec50d9f62544911e4b2ff1de589e452b7cfd0f786fd58fcdf5ecf80b6405304db173bba5

And how did you recovered it? I'd like to learn this.
legendary
Activity: 2268
Merit: 18711
And also, there is something called coinbase which is where all root outputs come from.
The coinbase transaction is the first transaction in each block in which the miner who found that block sends the block reward of (currently) 6.25 BTC brand new bitcoin to themselves, along with the transaction fees collected from all the transactions within that block they just found.

I have more questions, can an address have spent outputs with a positive balance?
Absolutely. If I send two outputs of 1 BTC each to an address, and then spend one of those bitcoin, the address will have used up an output and will still have a balance of 1 BTC.

For example, this account has 17 BTC (balance), it has received 20 BTC and sent 3 BTC, then it is pubkey exposed? (I'm unsure if it works like this)
Yes. To make any transaction the pubkey is exposed. The remaining balance on the address (or lack thereof) is irrelevant.

For the address you have linked, the public key is in uncompressed format and is as follows:
Code:
044188e7b878d0d88872ba579b8bbdb05161d985f4063d520e751340a6ec50d9f62544911e4b2ff1de589e452b7cfd0f786fd58fcdf5ecf80b6405304db173bba5
newbie
Activity: 10
Merit: 15
Thanks again!

I read the following: "UTXOs are created through the consumption of existing UTXOs. Every Bitcoin transaction is composed of inputs and outputs. Inputs consume an existing UTXO, while outputs create a new UTXO."

And also, there is something called coinbase which is where all root outputs come from.

I have more questions, can an address have spent outputs with a positive balance?

For example, this account has 17 BTC (balance), it has received 20 BTC and sent 3 BTC, then it is pubkey exposed? (I'm unsure if it works like this)

https://www.blockchain.com/btc/address/18yGdLieoWDBrkfFcU6mSJJzNMMfRztDUg
legendary
Activity: 3472
Merit: 10611
I have another question, then I cannot know any pubkey from any unspent address, if I understood it correctly it's called utxo?
As I mentioned above it depends on that output's script:
- Most of them (P2PKH, P2SH, P2MS, P2WPKH and P2WSH) only contain a hash and since hashes are not reversible you can't know the message that was hashed (pubkey or script in case of P2SH and P2WSH) without the owner spending from that address.
- But if it is one of the scripts that already contains the public key like P2PK you can easily see the pubkey in the output script. Taproot (P2TR) is slightly different as it contains a tweaked pubkey.

Quote
So, utxo which means unspent transaction output, now I can understand, but correct me if I'm wrong:

So if utxo belongs to output then it means there is a receiver, but if it's unspent it's because there isn't any sender.

But then, the following question assaults me, how is a utxo created, so if I only have a receiver who sent the money? You can create an address from real money? Or what is going on here?
Basically each bitcoin transaction contains 2 arrays: txins aka inputs and txouts aka outputs. If the output is not yet spent we call it a UTXO.
The inputs of a transaction and UTXOs from other previous transactions.
You can read more about raw transaction format here: https://developer.bitcoin.org/reference/transactions.html#raw-transaction-format
newbie
Activity: 10
Merit: 15
Thanks for your quick response!

I have another question, then I cannot know any pubkey from any unspent address, if I understood it correctly it's called utxo?

So, utxo which means unspent transaction output, now I can understand, but correct me if I'm wrong:

So if utxo belongs to output then it means there is a receiver, but if it's unspent it's because there isn't any sender.

But then, the following question assaults me, how is a utxo created, so if I only have a receiver who sent the money? You can create an address from real money? Or what is going on here?
legendary
Activity: 3472
Merit: 10611
You can recover possible candidate public keys by having ECDSA signature and the message [hash]. But in bitcoin transactions you don't need to because the public key is already included in any transaction that has a OP_CHECK(MULTI)SIG(VERIFY) op code.
When spending a P2PKH output, the public key is the top stack element when reaching OP_CHECKSIG.
When spending a P2WPKH output, the public key is the second witness item.
When spending a P2PK output, the public key is in the output.
When spending a P2TR output, the public key is a tweaked pubkey in the output (the witness program).
When spending other scripts such as P2SH when you reach any of the above op codes it should be the top stack element or in case of multi signatures there are multiple pubkeys.

then which pubkey is exposed, from the one that sends the money or the one who receives it?
It depends. P2PK outputs are not used anymore but P2TR outputs are new and are used and in both the receiver's public key is revealed (tweaked pubkey in taproot). In most other output scripts only the hash of the receiver's pubkey is used.
But in all cases, one way or another, you will know sender's public key.

Quote
And which is the difference between tx input and tx output. Input is who receives the money and output who emits it?
Inputs are the coins being spent and outputs are the new coins being created.
So inputs belong to the sender and outputs belong to receiver.
newbie
Activity: 10
Merit: 15
Hi,

following the next topic: https://bitcointalksearch.org/topic/ecdsa-signatures-allow-recovery-of-the-public-key-6430 and I have several newbie questions...

I would like to recover the public key from an address. I think the only way to do it is to check if there is any transaction done, but if a tx is done, then which pubkey is exposed, from the one that sends the money or the one who receives it?

And which is the difference between tx input and tx output. Input is who receives the money and output who emits it?

Also, I had check the bitcoin wiki, and I saw that there is a OP_CHECKSIG opcode: https://en.bitcoin.it/wiki/OP_CHECKSIG which states: "OP_CHECKSIG expects two values to be on the stack. These are, in order of stack depth, the public key and the signature of the script."

I think that the owner's pubkey is not exposed there, so, which pubkey does it refers to?

But I saw that with an ECDSA signature you can recover the original public key.

In that case, the ECDSA signature is from the person who emits the money?
Jump to: