<p>Firstly, it is very dangerous to convert a public address to a different form and then use it, because the owner of that address will not be expecting payments on other forms, and could result in fund loss. Only use addresses which the recipient has asked you to use.</p>

<p>But there is a difference between a compressed public key and an address. Bitcoin addresses starting with <code>1</code> are base58 encoded keyhash with a checksum. To get the key hash which is the ripemd/sha256 hash of the public key, you must decode the base58 and ensure the checksum is correct. Then you simply use the keyhash in the redeem script, you don't need to perform any more hashing on it to form the P2WPKH script. Notice that there is no way to know if an address starting with a 1 used a compressed or uncompressed public key before it's spent, so if you tried to convert one which had an uncompressed key, it would be unspendable, very dangerous as I said earlier.</p>

<p>See here for more details: <a href="https://bitcoincore.org/en/segwit_wallet_dev/#creation-of-p2sh-p2wpkh-address" rel="nofollow noreferrer">https://bitcoincore.org/en/segwit_wallet_dev/#creation-of-p2sh-p2wpkh-address</a></p>

CC BY-SA 3.0
2017-12-18T09:53:48.657Z
2017-12-18T09:53:48.657Z
meshcollider
<p>Java code doing that was pasted <a href="https://bitcoin.stackexchange.com/a/67029/51045">here</a>, but mostly without any explanation, so I'll try to explain.</p>

<p>When I was looking information about it, the best example was found in <a href="https://github.com/bitcoin/bips/blob/master/bip-0049.mediawiki#test-vectors" rel="nofollow noreferrer">BIP-49</a> text. We start from the following line:</p>

<pre><code>// Address derivation
keyhash = HASH160(account0recvPublickKeyHex) = 0x38971f73930f6c141d977ac4fd4a727c854935b3
</code></pre>

<p>So we have 20 bytes of public key hash: &lt; keyhash >. If we want to obtain legacy key, we simply prepend &lt; prefixByte > (prefixByte = 0 for BTC main) and get &lt; prefixByte | keyhash > array. Then we should do HASH160(&lt; prefixByte | keyhash >), and take first 4 bytes as checksum. So the resulting address looks like &lt; 0 | keyhash | checksum > - 25 bytes total. It is an address in his hex form. To get a common form we should only base58-encode it.</p>

<p>If we want to obtain a segwit-address, first we want to get &lt; keyhash >. We should decode base58-encoded address to an &lt; addressArray > and check the checksum (that last 4 bytes are equal to HASH160 of first 21). If everything is correct, we should drop first one and last four bytes of &lt; addressArray > to obtain a &lt; keyhash >.</p>

<p>The next step is to get a &lt; scriptSig >, simply prepending 0x0014 bytes to a &lt; keyhash > array:</p>

<pre><code>scriptSig = &lt; 0 &lt; keyhash &gt; &gt; = 0x001438971f73930f6c141d977ac4fd4a727c854935b3
</code></pre>

<p>We get segwitBytes hashing &lt; scriptSig >:</p>

<pre><code>segwitBytes = HASH160(scriptSig) = 0x336caa13e08b96080a32b5d818d59b4ab3b36742
</code></pre>

<p>And finally, we get an address, prepending p2shHeader (=5 for BTC MainNet, 196 for BTC Testnet) to segwitBytes, and appends their checksum:</p>

<pre><code>// segwitBytes base58check encoded for testnet
address = base58check(p2shHeader | segitBytes) = 2Mww8dCYPUpKHofjgcXcBCEGmniw9CoaiD2 (testnet)
</code></pre>

<p>HASH160 is following: first we use SHA256 function to hash and than RIPEMD160 on result. The example implemented in Java can be found for example <a href="https://github.com/bitcoinj/bitcoinj/blob/master/core/src/main/java/org/bitcoinj/core/Utils.java" rel="nofollow noreferrer">here</a> (function org.bitcoinj.core.Utils.sha256hash160).</p>

CC BY-SA 3.0
2017-12-30T20:38:25.617Z
2017-12-30T20:38:25.617Z
Sovan
<p>you may need to use hex values to do the conversion. Bitcoin doesn't work with strings/chars... When I do the calc at the terminal, I get your result (e.g. for the SHA256 to ripemd160):</p>

<pre><code>printf 151de228f6bec7635097f7813786830505d04bf56806f11eb056441fdc917d41 | openssl dgst -ripemd160
(stdin)= 9bbfb2424372d687cf35fd7d1e978f85a11157ca
</code></pre>

<p>But this would be the wrong way. You first would need to convert to hex, like this:</p>

<pre><code>$ printf 151de228f6bec7635097f7813786830505d04bf56806f11eb056441fdc917d41 &gt; tmp_sha256.txt
$ printf $( cat tmp_sha256.txt | sed 's/[[:xdigit:]]\{2\}/\\x&amp;/g' ) &gt; tmp_sha256.hex
$ hexdump -C tmp_sha256.hex 
00000000  15 1d e2 28 f6 be c7 63  50 97 f7 81 37 86 83 05  |...(...cP...7...|
00000010  05 d0 4b f5 68 06 f1 1e  b0 56 44 1f dc 91 7d 41  |..K.h....VD...}A|
00000020
</code></pre>

<p>then you can convert to next step like this:</p>

<pre><code>$ openssl dgst -ripemd160 tmp_sha256.hex 
RIPEMD160(tmp_sha256.hex)= db151e871af66b1323893e3f527e22f7684718af
</code></pre>

<p>all in all:</p>

<pre><code>$ printf 1L88S26C5oyjL1gkXsBeYwHHjvGvCcidr9 &gt; adr.txt
$ printf $( cat adr.txt | sed 's/[[:xdigit:]]\{2\}/\\x&amp;/g' ) &gt;adr.hex
$ openssl dgst -sha256 -binary &lt;adr.hex &gt;tmp_sha256.hex
$ hexdump -C tmp_sha256.hex 
$ openssl dgst -ripemd160  &lt;tmp_sha256.hex
</code></pre>

<p>returns a string now (56379c7bcd6b41188854e74169f844e8676cf8b8), that is then base58encoded into this address: </p>

<blockquote>
  <p>39YteymR86cG7V3Kijg8Gm2ST1r4nTeM1b</p>
</blockquote>

CC BY-SA 3.0
2017-12-16T18:04:17.270Z
how did you get 56379c7bcd6b41188854e74169f844e8676cf8b8?
Tailer
CC BY-SA 3.0
2017-12-17T08:10:54.047Z
when you don't provide an output file to openssl, and remove the "-binary", then it writes to the console: "openssl dgst -ripemd160  <tmp_sha256.hex". Are you on Windows or Unixoide systems?
pebwindkraft
CC BY-SA 3.0
2017-12-17T16:10:27.333Z
No, i'm not on windows.
performing the third step returns 
-bash: svn.hex: No such file or directory
Tailer
CC BY-SA 3.0
2017-12-17T23:03:03.780Z
oops, I should stay consistent with my filenames. it must be "openssl dgst -sha256 -binary <adr.hex >tmp_sha256.hex". (I did several tries, and first I used filenames "svn", and then "adr" ...). I just double checked it, it works now.
pebwindkraft
CC BY-SA 3.0
2017-12-18T02:51:09.377Z
Yeah, i got it now, but converting it to base58 returns 2CffxtJsCdzJEaHXHjSkvb12p12P 
tool: http://lenschulwitz.com/base58
Are you using bash or i missed something?
Tailer
CC BY-SA 3.0
2017-12-18T09:54:31.577Z
This approach is quite wrong, see my answer
meshcollider
CC BY-SA 3.0
2017-12-29T18:24:31.623Z
I also get "CffxtJsCdzJEaHXHjSkvb12p12P" as result. Unfortunately, I dont understand whats wrong.
A.c
CC BY-SA 3.0
2017-12-29T18:57:49.673Z
I figured out that there is something missing in front and in the end of "56379c7bcd6b41188854e74169f844e8676cf8b8". Can you help me out? There seems to be a "05" in the front and "6e1b34ba" at the end. Why is that?
A.c
CC BY-SA 3.0
2017-12-29T23:01:04.360Z
Can you help me here? https://bitcoin.stackexchange.com/questions/66957/convert-between-string-hex-byte-wrong-format
A.c
CC BY-SA 3.0
2017-12-30T07:15:54.063Z
nope, sorry, never played with Java and hash functions... but there is a library, where similiar code is used; maybe this helps: https://github.com/ValleZ/Paper-Wallet/blob/master/app/src/main/java/ru/valle/btc/BTCUtils.java
pebwindkraft
CC BY-SA 3.0
2017-12-31T00:08:27.147Z
@A.c as I said, this answer is incorrect, you should *not* hash the address, see my answer
meshcollider
CC BY-SA 3.0
2017-12-16T17:41:17.690Z
2017-12-17T23:00:30.383Z
2017-12-17T23:00:30.383Z
pebwindkraft
<p>I would like to calculate the segwit address of a public address.</p>

<pre><code>First step: 
take the compressed public address:
1L88S26C5oyjL1gkXsBeYwHHjvGvCcidr9

do a sha256 on that address:
151de228f6bec7635097f7813786830505d04bf56806f11eb056441fdc917d41

do a ripemd160:
9bbfb2424372d687cf35fd7d1e978f85a11157ca

encode with Base58:
usT1ggHqtEAcGd4ZysWqtxaaQmT
</code></pre>

<p>There is something wrong since every segwit address should start with "3". <strong>Can someone help me which step it is?</strong></p>

<p>My source of how a segwit address is calculated is: <a href="https://bitcoin.stackexchange.com/questions/63472/how-to-get-legacy-address-and-private-key-from-segwit-p2sh-address">How to get legacy address and private key from Segwit P2SH address?</a> Quote:</p>

<blockquote>
  <p>You have the private key so you can just derive the address from there. Get the corresponding public key, hash it with SHA256 and then that result with RIPEMD160. Then perform Base58Check Encoding on it.</p>
</blockquote>

CC BY-SA 3.0
2017-12-16T17:43:13.717Z
next to my answer below, see at the response here: https://bitcoin.stackexchange.com/questions/46455/verifying-a-bitcoin-trx-on-the-unix-cmd-line-with-openssl
pebwindkraft
<bitcoin-core><segregated-witness>
Calculate Segwit address from public address
A.c
# Calculate Segwit address from public address

(Asked by: username_0 on 2017-12-15)

I would like to calculate the segwit address of a public address.

```
First step: 
take the compressed public address:
1L88S26C5oyjL1gkXsBeYwHHjvGvCcidr9

do a sha256 on that address:
151de228f6bec7635097f7813786830505d04bf56806f11eb056441fdc917d41

do a ripemd160:
9bbfb2424372d687cf35fd7d1e978f85a11157ca

encode with Base58:
usT1ggHqtEAcGd4ZysWqtxaaQmT

```

There is something wrong since every segwit address should start with "3". **Can someone help me which step it is?**

My source of how a segwit address is calculated is: [How to get legacy address and private key from Segwit P2SH address?](https://bitcoin.stackexchange.com/questions/63472/how-to-get-legacy-address-and-private-key-from-segwit-p2sh-address) Quote:

> You have the private key so you can just derive the address from there. Get the corresponding public key, hash it with SHA256 and then that result with RIPEMD160. Then perform Base58Check Encoding on it.

**Tags:** bitcoin-core, segregated-witness

> **Comments:**
> **username_1**: next to my answer below, see at the response here: https://bitcoin.stackexchange.com/questions/46455/verifying-a-bitcoin-trx-on-the-unix-cmd-line-with-openssl  

---

## 3 answers

### Answer by username_2 on 2017-12-18. Score: 4

Firstly, it is very dangerous to convert a public address to a different form and then use it, because the owner of that address will not be expecting payments on other forms, and could result in fund loss. Only use addresses which the recipient has asked you to use.

But there is a difference between a compressed public key and an address. Bitcoin addresses starting with `1` are base58 encoded keyhash with a checksum. To get the key hash which is the ripemd/sha256 hash of the public key, you must decode the base58 and ensure the checksum is correct. Then you simply use the keyhash in the redeem script, you don't need to perform any more hashing on it to form the P2WPKH script. Notice that there is no way to know if an address starting with a 1 used a compressed or uncompressed public key before it's spent, so if you tried to convert one which had an uncompressed key, it would be unspendable, very dangerous as I said earlier.

See here for more details: <https://bitcoincore.org/en/segwit_wallet_dev/#creation-of-p2sh-p2wpkh-address>


---

### Answer by username_3 on 2017-12-30. Score: 3

Java code doing that was pasted [here](https://bitcoin.stackexchange.com/a/67029/51045), but mostly without any explanation, so I'll try to explain.

When I was looking information about it, the best example was found in [BIP-49](https://github.com/bitcoin/bips/blob/master/bip-0049.mediawiki#test-vectors) text. We start from the following line:

```
// Address derivation
keyhash = HASH160(account0recvPublickKeyHex) = 0x38971f73930f6c141d977ac4fd4a727c854935b3

```

So we have 20 bytes of public key hash: < keyhash >. If we want to obtain legacy key, we simply prepend < prefixByte > (prefixByte = 0 for BTC main) and get < prefixByte | keyhash > array. Then we should do HASH160(< prefixByte | keyhash >), and take first 4 bytes as checksum. So the resulting address looks like < 0 | keyhash | checksum > - 25 bytes total. It is an address in his hex form. To get a common form we should only base58-encode it.

If we want to obtain a segwit-address, first we want to get < keyhash >. We should decode base58-encoded address to an < addressArray > and check the checksum (that last 4 bytes are equal to HASH160 of first 21). If everything is correct, we should drop first one and last four bytes of < addressArray > to obtain a < keyhash >.

The next step is to get a < scriptSig >, simply prepending 0x0014 bytes to a < keyhash > array:

```
scriptSig = < 0 < keyhash > > = 0x001438971f73930f6c141d977ac4fd4a727c854935b3

```

We get segwitBytes hashing < scriptSig >:

```
segwitBytes = HASH160(scriptSig) = 0x336caa13e08b96080a32b5d818d59b4ab3b36742

```

And finally, we get an address, prepending p2shHeader (=5 for BTC MainNet, 196 for BTC Testnet) to segwitBytes, and appends their checksum:

```
// segwitBytes base58check encoded for testnet
address = base58check(p2shHeader | segitBytes) = 2Mww8dCYPUpKHofjgcXcBCEGmniw9CoaiD2 (testnet)

```

HASH160 is following: first we use SHA256 function to hash and than RIPEMD160 on result. The example implemented in Java can be found for example [here](https://github.com/bitcoinj/bitcoinj/blob/master/core/src/main/java/org/bitcoinj/core/Utils.java) (function org.bitcoinj.core.Utils.sha256hash160).


---

### Answer by username_1 on 2017-12-16. Score: 0

you may need to use hex values to do the conversion. Bitcoin doesn't work with strings/chars... When I do the calc at the terminal, I get your result (e.g. for the SHA256 to ripemd160):

```
printf 151de228f6bec7635097f7813786830505d04bf56806f11eb056441fdc917d41 | openssl dgst -ripemd160
(stdin)= 9bbfb2424372d687cf35fd7d1e978f85a11157ca

```

But this would be the wrong way. You first would need to convert to hex, like this:

```
$ printf 151de228f6bec7635097f7813786830505d04bf56806f11eb056441fdc917d41 > tmp_sha256.txt
$ printf $( cat tmp_sha256.txt | sed 's/[[:xdigit:]]\{2\}/\\x&/g' ) > tmp_sha256.hex
$ hexdump -C tmp_sha256.hex 
00000000  15 1d e2 28 f6 be c7 63  50 97 f7 81 37 86 83 05  |...(...cP...7...|
00000010  05 d0 4b f5 68 06 f1 1e  b0 56 44 1f dc 91 7d 41  |..K.h....VD...}A|
00000020

```

then you can convert to next step like this:

```
$ openssl dgst -ripemd160 tmp_sha256.hex 
RIPEMD160(tmp_sha256.hex)= db151e871af66b1323893e3f527e22f7684718af

```

all in all:

```
$ printf 1L88S26C5oyjL1gkXsBeYwHHjvGvCcidr9 > adr.txt
$ printf $( cat adr.txt | sed 's/[[:xdigit:]]\{2\}/\\x&/g' ) >adr.hex
$ openssl dgst -sha256 -binary <adr.hex >tmp_sha256.hex
$ hexdump -C tmp_sha256.hex 
$ openssl dgst -ripemd160  <tmp_sha256.hex

```

returns a string now (56379c7bcd6b41188854e74169f844e8676cf8b8), that is then base58encoded into this address:

> 39YteymR86cG7V3Kijg8Gm2ST1r4nTeM1b

> **Comments:**
> **username_4**: how did you get 56379c7bcd6b41188854e74169f844e8676cf8b8?  
> **username_1**: when you don't provide an output file to openssl, and remove the "-binary", then it writes to the console: "openssl dgst -ripemd160  <tmp_sha256.hex". Are you on Windows or Unixoide systems?  
> **username_4**: No, i'm not on windows. performing the third step returns  -bash: svn.hex: No such file or directory  
> **username_1**: oops, I should stay consistent with my filenames. it must be "openssl dgst -sha256 -binary <adr.hex >tmp_sha256.hex". (I did several tries, and first I used filenames "svn", and then "adr" ...). I just double checked it, it works now.  
> **username_4**: Yeah, i got it now, but converting it to base58 returns 2CffxtJsCdzJEaHXHjSkvb12p12P  tool: http://lenschulwitz.com/base58 Are you using bash or i missed something?  
> **username_2**: This approach is quite wrong, see my answer  
> **username_0**: I also get "CffxtJsCdzJEaHXHjSkvb12p12P" as result. Unfortunately, I dont understand whats wrong.  
> **username_0**: I figured out that there is something missing in front and in the end of "56379c7bcd6b41188854e74169f844e8676cf8b8". Can you help me out? There seems to be a "05" in the front and "6e1b34ba" at the end. Why is that?  
> **username_0**: Can you help me here? https://bitcoin.stackexchange.com/questions/66957/convert-between-string-hex-byte-wrong-format  
> **username_1**: nope, sorry, never played with Java and hash functions... but there is a library, where similiar code is used; maybe this helps: https://github.com/ValleZ/Paper-Wallet/blob/master/app/src/main/java/ru/valle/btc/BTCUtils.java  
> **username_2**: @username_0 as I said, this answer is incorrect, you should *not* hash the address, see my answer  

---

