Author

Topic: How does one derive a SegWit address from a legacy address? [0.001 BTC Reward!] (Read 449 times)

legendary
Activity: 1042
Merit: 2805
Bitcoin and C♯ Enthusiast
This part is false.
G is not exactly a "constant" and is not derived from the curve. G is one of the point on the curve that we have chosen as the "generator" of the curve. And that means multiplying any value from 1 to order of G yields another point (not a string of characters!!) on the curve which would be your public key. And that is the basic of asymmetric cryptography.
So, you do say that they are not constant. But from what I have read in Mastering Bitcoin Book, the author says that "G is a constant point and they are always same for all keys in bitcoin."

Well, I said "not exactly" so it is somewhat correct and when I said "false" I mostly meant the second part of what I quoted.
But basically when you are talking about elliptic curves in general, G is simply a point on the curve. In a specific curve like secp256k1 which bitcoin uses, there is only one G that is used as a standard for that curve.
legendary
Activity: 1584
Merit: 1280
Heisenberg Design Services
@Coding Enthusiast Thanks for being more precise and correcting me. I would like to clear up few more things from what I have read.

This part is false.
G is not exactly a "constant" and is not derived from the curve. G is one of the point on the curve that we have chosen as the "generator" of the curve. And that means multiplying any value from 1 to order of G yields another point (not a string of characters!!) on the curve which would be your public key. And that is the basic of asymmetric cryptography.
So, you do say that they are not constant. But from what I have read in Mastering Bitcoin Book, the author says that "G is a constant point and they are always same for all keys in bitcoin."

This is false. Legacy transactions don't have higher size, they have higher weight.
Thanks for clearing it up. I was completely unaware of the weight, although I have read that segwits fees are calculated based on the virtual size of the tx.
full member
Activity: 434
Merit: 101
YouTuber, gambler, and scam-buster.
I have a question: since a legacy address corresponds to several SegWit addresses, how does your program know which one to get? I specifically need a way to derive 3H2miXstFo3jRFfz5ekcdZJNMfGSYHeNvB from the 1XXX address. Is this doable?

As far as I understand the algorithm, there is only one possible P2SH-P2WPKH with current and only witness program version and that's what this code is giving you.

https://gyazo.com/72b4eb7abbdc286520535da7cbea1648

Worked like a charm. Thank you so much!
legendary
Activity: 1042
Merit: 2805
Bitcoin and C♯ Enthusiast
I have a question: since a legacy address corresponds to several SegWit addresses, how does your program know which one to get? I specifically need a way to derive 3H2miXstFo3jRFfz5ekcdZJNMfGSYHeNvB from the 1XXX address. Is this doable?

As far as I understand the algorithm, there is only one possible P2SH-P2WPKH with current and only witness program version and that's what this code is giving you.
full member
Activity: 434
Merit: 101
YouTuber, gambler, and scam-buster.
I've added the files I mentioned above with a release which you don't have to use if you compile it yourself.
I've also added a bunch of comments in the main function to clarify what is happening. The rest of the code is also fully documented (since I copied them over from my main library project) so the functions purposes should be clear enough.

Cool. I'm currently installing both VS and .NET Core.

I have a question: since a legacy address corresponds to several SegWit addresses, how does your program know which one to get? I specifically need a way to derive 3H2miXstFo3jRFfz5ekcdZJNMfGSYHeNvB from the 1XXX address. Is this doable?
legendary
Activity: 1042
Merit: 2805
Bitcoin and C♯ Enthusiast
I've added the files I mentioned above with a release which you don't have to use if you compile it yourself.
I've also added a bunch of comments in the main function to clarify what is happening. The rest of the code is also fully documented (since I copied them over from my main library project) so the functions purposes should be clear enough.
full member
Activity: 434
Merit: 101
YouTuber, gambler, and scam-buster.
That would be a massive help! If you can code up something that links the two addresses, or point me towards an online resource that does the job, it would be amazing. You'll get the reward as well, if you care for that sort of thing  Tongue Bless you!

Here you go. https://github.com/Coding-Enthusiast/AddrConverter (going to add ReadMe, License and release in a minute)
And don't worry about "reward".

Thank you very much! I've never run something like this before, so I'm currently installing Visual Studio to open this up. Feel free to drop your bitcoin address anytime. If this works, I'll update the thread. I appreciate it!
legendary
Activity: 1042
Merit: 2805
Bitcoin and C♯ Enthusiast
That would be a massive help! If you can code up something that links the two addresses, or point me towards an online resource that does the job, it would be amazing. You'll get the reward as well, if you care for that sort of thing  Tongue Bless you!

Here you go. https://github.com/Coding-Enthusiast/AddrConverter (going to add ReadMe, License and release in a minute)
And don't worry about "reward".
full member
Activity: 434
Merit: 101
YouTuber, gambler, and scam-buster.
Thanks. So I'm trying to figure out how to do the first method, but I'm not sure which app or website to input the steps in. I tried it in Bitcoin Core and coinb.in; didn't seem to work. Please do excuse my ineptitude.

Well those applications all have the code to do all these stuff but they don't usually expose the functions through any kind of CLI because it is not used. You'll have to write something yourself. I can put together something for you in c# for the first part only (not the public key recovery) if you like.

That would be a massive help! If you can code up something that links the two addresses, or point me towards an online resource that does the job, it would be amazing. You'll get the reward as well, if you care for that sort of thing  Tongue Bless you!
legendary
Activity: 1042
Merit: 2805
Bitcoin and C♯ Enthusiast
Thanks. So I'm trying to figure out how to do the first method, but I'm not sure which app or website to input the steps in. I tried it in Bitcoin Core and coinb.in; didn't seem to work. Please do excuse my ineptitude.

Well those applications all have the code to do all these stuff but they don't usually expose the functions through any kind of CLI because it is not used. You'll have to write something yourself. I can put together something for you in c# for the first part only (not the public key recovery) if you like.
full member
Activity: 434
Merit: 101
YouTuber, gambler, and scam-buster.
how to link the 1XXX address to the 3XXX address without me having to retrieve the Ledger from its stored location.

Things you can not do:
- Get the 1xxx address from 3xxx address
Things you can do:
- Get the 3xxx address from the 1xxx address1
- Get either 1xxx or 3xxx or basically anything else if you have published a signature with a message that you signed (this includes transactions that were spent from that key)!2

Here are the steps for (1)
1. Having the address starting with 1, perform a Base58check_decode on it to get the byte array remove the first byte as it is the version byte. The next 20 bytes are the hash160 (you can also open the address in blockchain.com explorer and it shows you the hash160 result!)
2. Write the "witness script" for the current version of SegWit which is
Code:
0x00 0x14 
3. Perform HASH160 hash on the result of step 2
Code:
RIPEMD160(SHA256())
4. Append the P2SH version byte (=0x05) to the beginning of the result of step 3 and perform a Base58Check_encode on the result
Code:
Base58.EncodeWithCheckSum(0x05 || )
=> now you have your P2SH-P2WPKH address that starts with 3.

Here are the steps for (2):
1. Decode your signature (base-64) and throw away the first byte. Then your first 32 bytes are your r value in little-endian order and the second one is s.
2. Append the default message to  your message (Bitcoin Signed Message:\n) with its length. Compute double SHA256 of it. This is the "message".
3. Recover your public key by knowing (r,s) and message. (I haven't released my library yet to add that as a reference but you should be able to find  this option in any library such as OpenSSL that has ECDSA capabilities)
4. Perform HASH160 on the compressed public key as bytes.
5. Feed it to step 2 of above.

This is the reference but in my opinion it is very vague: https://bitcoincore.org/en/segwit_wallet_dev/

Thanks. So I'm trying to figure out how to do the first method, but I'm not sure which app or website to input the steps in. I tried it in Bitcoin Core and coinb.in; didn't seem to work. Please do excuse my ineptitude.
legendary
Activity: 1042
Merit: 2805
Bitcoin and C♯ Enthusiast
how to link the 1XXX address to the 3XXX address without me having to retrieve the Ledger from its stored location.

Things you can not do:
- Get the 1xxx address from 3xxx address
Things you can do:
- Get the 3xxx address from the 1xxx address1
- Get either 1xxx or 3xxx or basically anything else if you have published a signature with a message that you signed (this includes transactions that were spent from that key)!2

Here are the steps for (1)
1. Having the address starting with 1, perform a Base58check_decode on it to get the byte array remove the first byte as it is the version byte. The next 20 bytes are the hash160 (you can also open the address in blockchain.com explorer and it shows you the hash160 result!)
2. Write the "witness script" for the current version of SegWit which is
Code:
0x00 0x14 
3. Perform HASH160 hash on the result of step 2
Code:
RIPEMD160(SHA256())
4. Append the P2SH version byte (=0x05) to the beginning of the result of step 3 and perform a Base58Check_encode on the result
Code:
Base58.EncodeWithCheckSum(0x05 || )
=> now you have your P2SH-P2WPKH address that starts with 3.

Here are the steps for (2):
1. Decode your signature (base-64) and throw away the first byte. Then your first 32 bytes are your r value in little-endian order and the second one is s.
2. Append the default message to  your message (Bitcoin Signed Message:\n) with its length. Compute double SHA256 of it. This is the "message".
3. Recover your public key by knowing (r,s) and message. (I haven't released my library yet to add that as a reference but you should be able to find  this option in any library such as OpenSSL that has ECDSA capabilities)
4. Perform HASH160 on the compressed public key as bytes.
5. Feed it to step 2 of above.

This is the reference but in my opinion it is very vague: https://bitcoincore.org/en/segwit_wallet_dev/
full member
Activity: 434
Merit: 101
YouTuber, gambler, and scam-buster.
Just curious, is there any documentation as to how you just did that?
Standards for Efficient Cryptography SEC 1: Elliptic Curve Cryptography
Section 4.1.6 Public Key Recovery Operation (Page 47)

That's pretty cool, thanks.

So I've been Googling around. Using validateaddress in Bitcoin Core gives me "scriptPubKey": "a914a84658b58e2bd0e62bfb1905dfcc19415bf99ff387" when I submit the address 3H2miXstFo3jRFfz5ekcdZJNMfGSYHeNvB. I wonder if this has any relation to the public key or the 1XXX address.
I honestly don't know. I still have not been able to figure out how this particular type of address is derived from keys.

Damn, that sucks.

Welp, for the next 24 hours, I'll give a 0.001 BTC reward to anyone who can figure out how to link the 1XXX address to the 3XXX address without me having to retrieve the Ledger from its stored location. I sure as hell can't figure it out; maybe someone else can. The reward will expire after a day, because I may want to spend my money after that  Grin
legendary
Activity: 1042
Merit: 2805
Bitcoin and C♯ Enthusiast
Just curious, is there any documentation as to how you just did that?
Standards for Efficient Cryptography SEC 1: Elliptic Curve Cryptography
Section 4.1.6 Public Key Recovery Operation (Page 47)

That's pretty cool, thanks.

So I've been Googling around. Using validateaddress in Bitcoin Core gives me "scriptPubKey": "a914a84658b58e2bd0e62bfb1905dfcc19415bf99ff387" when I submit the address 3H2miXstFo3jRFfz5ekcdZJNMfGSYHeNvB. I wonder if this has any relation to the public key or the 1XXX address.
I honestly don't know. I still have not been able to figure out how this particular type of address is derived from keys.
full member
Activity: 434
Merit: 101
YouTuber, gambler, and scam-buster.
Thank you, this is the closest thing to the answer I'm looking for in the thread.

Another question: I've locked up my Ledger for the time being. Is it possible to prove the link between the 1XXX address and the 3XXX address without having to re-sign another transaction?

By the way, here is the signature in question: https://bitcointalksearch.org/topic/m.50361478

I have actually never had the chance to learn how nested-SegWit addresses work. But since they are derived from one public key and by publishing your signature + your address (1xxx) you are revealing your public key, it should not be hard to get the 3xxx address from it.
The public key of the address you linked is:
Code:
02ec5d3485b27e3721a34f71065892f1d3be2d7b2f57970d768239810e0074e978

That's pretty cool, thanks.

So I've been Googling around. Using validateaddress in Bitcoin Core gives me "scriptPubKey": "a914a84658b58e2bd0e62bfb1905dfcc19415bf99ff387" when I submit the address 3H2miXstFo3jRFfz5ekcdZJNMfGSYHeNvB. I wonder if this has any relation to the public key or the 1XXX address.
legendary
Activity: 1946
Merit: 1427
Thank you, this is the closest thing to the answer I'm looking for in the thread.

Another question: I've locked up my Ledger for the time being. Is it possible to prove the link between the 1XXX address and the 3XXX address without having to re-sign another transaction?

By the way, here is the signature in question: https://bitcointalksearch.org/topic/m.50361478

I have actually never had the chance to learn how nested-SegWit addresses work. But since they are derived from one public key and by publishing your signature + your address (1xxx) you are revealing your public key, it should not be hard to get the 3xxx address from it.
The public key of the address you linked is:
Code:
02ec5d3485b27e3721a34f71065892f1d3be2d7b2f57970d768239810e0074e978
Just curious, is there any documentation as to how you just did that?
legendary
Activity: 1042
Merit: 2805
Bitcoin and C♯ Enthusiast
Thank you, this is the closest thing to the answer I'm looking for in the thread.

Another question: I've locked up my Ledger for the time being. Is it possible to prove the link between the 1XXX address and the 3XXX address without having to re-sign another transaction?

By the way, here is the signature in question: https://bitcointalksearch.org/topic/m.50361478

I have actually never had the chance to learn how nested-SegWit addresses work. But since they are derived from one public key and by publishing your signature + your address (1xxx) you are revealing your public key, it should not be hard to get the 3xxx address from it.
The public key of the address you linked is:
Code:
02ec5d3485b27e3721a34f71065892f1d3be2d7b2f57970d768239810e0074e978
full member
Activity: 434
Merit: 101
YouTuber, gambler, and scam-buster.


In any case to answer OP's question the problem is that when you are proving ownership of an address, what you really are doing is that you are creating a signature similar to when you sign a transaction. And when others verify that, what they really do is that they recover your public key from that signature then verify whether it is valid or not.
Where does address come in? Basically nowhere. We also include the address because when they recover your public key from your signature they might end up with multiple possible public keys, including the address helps narrow the possibilities down to only 1.
What about SegWit addresses come in? The problem is that there still is no standard for them. I saw one of these hardware wallets (Trezor?) had a personal defined standard where they added 1 byte to the first byte of the signatures. But apart from that, you won't find anything globally accepted.

Since this IS possible your only option is to ask the wallet developers to add such functionality for you or come to some sort of agreement with the other party you are trying to do a "proof of funds" with to come up with some sort of standard like sending a transaction out of the address with a message attached would work but it will cost you fees.

Thank you, this is the closest thing to the answer I'm looking for in the thread.

Another question: I've locked up my Ledger for the time being. Is it possible to prove the link between the 1XXX address and the 3XXX address without having to re-sign another transaction?

By the way, here is the signature in question: https://bitcointalksearch.org/topic/m.50361478
legendary
Activity: 1042
Merit: 2805
Bitcoin and C♯ Enthusiast
G = Constant from the elliptic curve
The constant G is derived from Elliptic Curve and when you multiply your generated Private Key with the Constant, it will yield a new string of characters known as the public key.
This part is false.
G is not exactly a "constant" and is not derived from the curve. G is one of the point on the curve that we have chosen as the "generator" of the curve. And that means multiplying any value from 1 to order of G yields another point (not a string of characters!!) on the curve which would be your public key. And that is the basic of asymmetric cryptography.

A legacy address is the common address used in the early days and will generate a higher transaction size.
This is false. Legacy transactions don't have higher size, they have higher weight.

Address = Base58check_encode(version_byte || RIPEMD160[SHA256[PubKey]]])
FTFY

The resulting version of the hash is longer enough, hence they are encoded using Base58 encoding method which brings down the total character to 58.
This if false. The number of characters can be different and it is between 25-34.
58 is the total number of characters in the base we are encoding this to. eg. Base-16 has 16 characters.


In any case to answer OP's question the problem is that when you are proving ownership of an address, what you really are doing is that you are creating a signature similar to when you sign a transaction. And when others verify that, what they really do is that they recover your public key from that signature then verify whether it is valid or not.
Where does address come in? Basically nowhere. We also include the address because when they recover your public key from your signature they might end up with multiple possible public keys, including the address helps narrow the possibilities down to only 1.
What about SegWit addresses come in? The problem is that there still is no standard for them. I saw one of these hardware wallets (Trezor?) had a personal defined standard where they added 1 byte to the first byte of the signatures. But apart from that, you won't find anything globally accepted.

Since this IS possible your only option is to ask the wallet developers to add such functionality for you or come to some sort of agreement with the other party you are trying to do a "proof of funds" with to come up with some sort of standard like sending a transaction out of the address with a message attached would work but it will cost you fees.
legendary
Activity: 2758
Merit: 6830
AFAIK, there is no way to prove one is connected to the other without providing your private key.

But you should be able to use a different wallet that supports signing messages with Segwit addresses to do it.

Well, that sucks. I just got back after locking my Ledger in a safe deposit box in Malaysia  Undecided
Oh sorry, I actually thought you were talking about Electrum instead of Ledger for some reason. Exporting the private key to sign it in a different wallet would break your hardware wallet security. So that’s not recommended.
full member
Activity: 434
Merit: 101
YouTuber, gambler, and scam-buster.
AFAIK, there is no way to prove one is connected to the other without providing your private key.

But you should be able to use a different wallet that supports signing messages with Segwit addresses to do it.

Well, that sucks. I just got back after locking my Ledger in a safe deposit box in Malaysia  Undecided
legendary
Activity: 2758
Merit: 6830
AFAIK, there is no way to prove one is connected to the other without providing your private key.

But you should be able to use a different wallet that supports signing messages with Segwit addresses to do it.
legendary
Activity: 1946
Merit: 1427
Thanks for the detailed response, Heisenberg_Hunter.

What I'm getting at is, how can I prove that I own the funds present at 3H2miXstFo3jRFfz5ekcdZJNMfGSYHeNvB if I can only sign a message from 1CmXjL8V2UJ8jQnMmVNCJtyTzSHPY4gyoR? Is it impossible for me to prove I own those funds simply because they are stored in a SegWit address, or is there some online app or block explorer that can prove that a signed message from 1CmXjL8V2UJ8jQnMmVNCJtyTzSHPY4gyoR also corresponds to the address 3H2miXstFo3jRFfz5ekcdZJNMfGSYHeNvB?
In theory, (atleast i think), you should be able to prove correlation if you've spend funds from both of the adresses.

Once you spend funds, the public key becomes known, which, should be the same for both of the adresses? (Not entirely sure if this is actually the case though.)

Otherwise, no, i don't think there's any way to prove to someone without the private key that you own both of the adresses. (Unless you use some sort of chain analysis as proof.)
full member
Activity: 434
Merit: 101
YouTuber, gambler, and scam-buster.
Thanks for the detailed response, Heisenberg_Hunter.

What I'm getting at is, how can I prove that I own the funds present at 3H2miXstFo3jRFfz5ekcdZJNMfGSYHeNvB if I can only sign a message from 1CmXjL8V2UJ8jQnMmVNCJtyTzSHPY4gyoR? Is it impossible for me to prove I own those funds simply because they are stored in a SegWit address, or is there some online app or block explorer that can prove that a signed message from 1CmXjL8V2UJ8jQnMmVNCJtyTzSHPY4gyoR also corresponds to the address 3H2miXstFo3jRFfz5ekcdZJNMfGSYHeNvB?
legendary
Activity: 1584
Merit: 1280
Heisenberg Design Services
, or how one or derived from the other? Thank you.

In order to understand how the addresses are generated, you need to have an insight on how the public keys and private keys are derived based on the elliptic curve algorithm which is being followed in the bitcoin. Every address is generated from the private keys. With a private key you can generate either a legacy address (that starts with 1) or a segregated witness address commonly known as segwit (that starts with 3 or bc1). Some wallets like electrum can generate only addresses which are of legacy type or native segwit or bech32 type.

A public key is generally derived from the private key with a help of one way multiplication function. This means that, you can generate a public key from the private key but you cannot do the other way (i.e a private key cannot be derived from a public key). A private key is a ordinary number which lies in between 1 and 2^256. I am not going deep inside about private keys and their functions, as it would become slightly off-topic and the post would become so lengthy and cumbersome.

A private key is a hexadecimal representation of 256 bit random number. From that hexadecimal number, you generate the public key by doing a multiplication. This multiplication can be represented by

K = k * G

where

G = Constant from the elliptic curve
k = Private Key
K = Public

The constant G is derived from Elliptic Curve and when you multiply your generated Private Key with the Constant, it will yield a new string of characters known as the public key.

Note that, it is a one way function where only multiplication is possible and dividing Public Key with constant won't yield you the Private Key.

Legacy Addresses

Once you have the Public Key, you can either generate a legacy address or a segwit address. A legacy address is the common address used in the early days and will generate a higher transaction size. With higher transaction sizes, you need to pay higher fees. Here with the generated public key, you will double hash them to get a resulting legacy address.

The public key is first hashed with Sha256 algorithm and the resulting number is hashed with RiPEMD160 algorithm. We can simply write this as,

Address = RIPEMD160[SHA256[PubKey]]]

The resulting version of the hash is longer enough, hence they are encoded using Base58 encoding method which brings down the total character to 58.

P2SH Addresses

A P2SH is similar to the hashing function, but here we don't hash the public key rather we double hash the script. Addresses that start with 3 are generally called as p2sh rather than calling them as segwit. Segwit removes unwanted witnesses which increases the size of a transaction significantly. By reducing the space, more transactions can be included in a block which certainly helps in scalability of the bitcoin network.

Yep, I surmised as much. What I'd like to know is, how do I see the list of SegWit addresses linked to that legacy address? I'd like to give proof of funds from a 3XXX address rather than a 1XXX address, so I want to figure out how the two are linked.
They are linked together only by private keys. With a single private key, you can either generate a legacy or a segwit address.
full member
Activity: 434
Merit: 101
YouTuber, gambler, and scam-buster.
Hello,

I signed a message from my Ledger, and selected the address 3H2miXstFo3jRFfz5ekcdZJNMfGSYHeNvB to sign from. When I signed the message, it got signed from the address 1CmXjL8V2UJ8jQnMmVNCJtyTzSHPY4gyoR, which I presume is the legacy address from which the first one was derived.

My question is, is there some online tool that can help me see the link between the two addresses, or how one or derived from the other? Thank you.

Legacy starts with 1

Segwit starts with 3 or bc1


In Ledger, you can not sing a message from a segwit address so by default it signs you a legacy address.


Yep, I surmised as much. What I'd like to know is, how do I see the list of SegWit addresses linked to that legacy address? I'd like to give proof of funds from a 3XXX address rather than a 1XXX address, so I want to figure out how the two are linked.
legendary
Activity: 2800
Merit: 2736
Farewell LEO: o_e_l_e_o
Hello,

I signed a message from my Ledger, and selected the address 3H2miXstFo3jRFfz5ekcdZJNMfGSYHeNvB to sign from. When I signed the message, it got signed from the address 1CmXjL8V2UJ8jQnMmVNCJtyTzSHPY4gyoR, which I presume is the legacy address from which the first one was derived.

My question is, is there some online tool that can help me see the link between the two addresses, or how one or derived from the other? Thank you.

Legacy starts with 1

Segwit starts with 3 or bc1


In Ledger, you can not sing a message from a segwit address so by default it signs you a legacy address.
full member
Activity: 434
Merit: 101
YouTuber, gambler, and scam-buster.
Hello,

I signed a message from my Ledger, and selected the address 3H2miXstFo3jRFfz5ekcdZJNMfGSYHeNvB to sign from. When I signed the message, it got signed from the address 1CmXjL8V2UJ8jQnMmVNCJtyTzSHPY4gyoR, which I presume is the legacy address from which the first one was derived.

My question is, is there some online tool that can help me see the link between the two addresses, or how one or derived from the other? Thank you.
Jump to: