<p>Bech32 encoding, apart from the checksum, is a simple matter of converting base-256 (8-bits) to base-32 (5-bits). Base-256 is the byte array (octet string) that you get from a hash function. Only focusing on first 3 bytes of the hash:  </p>

<pre><code>as hex    = 0x18     0x63     0x14 
as bytes  = 24       99       20 
as binary = 00011000 01100011 00010100 
</code></pre>

<p>In order to convert the above base-256 (8-bits) input to base-32 (5-bits) we start from the most significant bit and select 5 bits at a time until we run out.  </p>

<pre><code>12345123 45123451 23451234 ...
00011000 01100011 00010100
(00011) (00001) (10001) (10001) (0100 ...
</code></pre>

<p>For a bech-32 <em>address</em> there is an extra step here <strong>after the base conversion is done</strong>. That step is to append of the "witness version" to the beginning of this group as an already converted value in base-32 (since witness version is defined from 0 to 16 inclusive it is already in range).  </p>

<pre><code>[00000] (00011) (00001) (10001) (10001) (0100 ...
</code></pre>

<p>This final result can be converted to an array of <em>numbers</em> that are between 0 and 31  </p>

<pre><code>0, 3, 1, 17, 17
</code></pre>

<p>To convert this "number" array to human readable format we print the corresponding character from the bech32 charset (<code>qpzry9x8gf2tvdw0s3jn54khce6mua7l</code>)</p>

<pre><code>0-&gt;q, 3-&gt;r, 1-&gt;p, 17-&gt;3, 17-&gt;3 ...
</code></pre>

<p>P.S. There is a checksum calculation that I skipped to keep it simple but it is just another appended set of 5-bit values at the <em>end</em> of what we have in last step.</p>

CC BY-SA 4.0
2020-03-28T17:19:58.897Z
oh thanks, I just convert SHA256 digest into base2. it's not enough?
```SCRIPT_HASH=`printf $SCRIPT | xxd -r -p | openssl sha256| sed 's/^.* //'```
Then convert to base2```echo "ibase=16; obase=2; $(echo $SCRIPT_HASH | tr '[:lower:]' '[:upper:]') " | bc  | sed 's/\\//g' | tr -d '\n' > base2.txt```
monkeyUser
CC BY-SA 4.0
2020-03-28T21:37:09.770Z
that command is not correct echo `'ibase=16; obase=2; 18' | bc`? I use the same logic and script for P2WPKH and same logic to calculate Seed phrase. thanks again
monkeyUser
CC BY-SA 4.0
2020-04-06T15:07:57.287Z
I can generate P2WPKH without a problem with same logic, even your post in bitcoin talk (https://bitcointalk.org/index.php?topic=4992632.0). the P2WSH logic about Base2 is different?
monkeyUser
CC BY-SA 4.0
2020-04-06T15:14:16.220Z
I can't understand the code you posted so I can't tell which part of it is wrong. But you may be having a bug that works with 20 bytes input but not with 32. There is a padding involved when converting bits (20 byte = 160 bit % 5 = *0* but 32 byte = 256 bit % 5 = *1*).
Coding Enthusiast
CC BY-SA 4.0
2020-04-06T17:23:43.457Z
Enthusuast. Thanks for your time, it's very funny because with 20 byte it works. Anyway maybe I find a bug, but I have a new problem with checksum (in 20 byte is ok obviously)
monkeyUser
CC BY-SA 4.0
2020-03-28T16:38:04.430Z
2020-03-28T16:38:04.430Z
Coding Enthusiast
<p>I want to create P2WSH native like <a href="https://en.bitcoin.it/wiki/BIP_0173" rel="nofollow noreferrer">https://en.bitcoin.it/wiki/BIP_0173</a>.
I have already a script to generate P2WPKH and it works, thank the python part and re-arrange group byte works.</p>

<p>I read that witnessScript (scriptPubKey) is hash of SHA256 without RIPEMD160.
Below a little bit of my code.</p>

<pre><code>PB=0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798

#REDEEM SCRIPT &lt;Public Key&gt; OP_CHECKSIG
SCRIPT=210279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798AC

#SCRIPT HASH
$ printf $SCRIPT | xxd -r -p | openssl sha256| sed 's/^.* //'
1863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262

Convert scripthash to base 2
</code></pre>

<blockquote>
  <p>11000 01100 01100 01010 00011 11000 00101 00110 00101 00010 11001 10100 00000 01001 01111 01000 11001 00100 00000 11001 10101 01101
  10110 10000 10011 01101 10010 01100 00101 01100 11110 00110 01101
  01001 10100 10011 11010 00011 01110 00110 00110 00110 01010 01011
  00000 01001 00100 00001 10010 01100 010</p>
</blockquote>

<p>I need to add two zero at the beginning in order to Re-arrange those bits into groups of 5</p>

<blockquote>
  <p>00110 00011 00011 00010 10000 11110 00001 01001 10001 01000 10110
  01101 00000 00010 01011 11010 00110 01001 00000 00110 01101 01011
  01101 10100 00100 11011 01100 10011 00001 01011 00111 10001 10011
  01010 01101 00100 11110 10000 11011 10001 10001 10001 10010 10010
  11000 00010 01001 00000 01100 10011 00010</p>
</blockquote>

<p>Add witness program</p>

<blockquote>
  <p>00000 00110 00011 00011 00010 10000 11110 00001 01001 10001 01000 10110
  01101 00000 00010 01011 11010 00110 01001 00000 00110 01101 01011
  01101 10100 00100 11011 01100 10011 00001 01011 00111 10001 10011
  01010 01101 00100 11110 10000 11011 10001 10001 10001 10010 10010
  11000 00010 01001 00000 01100 10011 00010</p>
</blockquote>

<p>Convert each bits to base10</p>

<pre><code>0, 6, 3, 3, 2, 16, 30, 1, 9, 17, 8, 22, 13, 0, 2, 11, 26, 6, 9, 0, 6, 13, 11, 13, 20, 4, 27, 12, 19, 1, 11, 7, 17, 19, 10, 13, 4, 30, 16, 27, 17, 17, 17, 18, 18, 24, 2, 9, 0, 12, 19, 2    
</code></pre>

<p>Create the checksum with python code</p>

<pre><code>15
29
21
28
10
6
</code></pre>

<p>my result is:</p>

<pre><code>tb1qxrrzs7pf3gkdqzt6xfqxdtd5ymvnpt83n2dy7sm333jjczfqvnz0a4u2x
</code></pre>

<p>but the result in BIP 0173 is</p>

<pre><code>tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7
</code></pre>

<p>I use the same script to generate P2WPKH that you can find in BIP_173 and it works. Of course I change Public key with public key hash, but the logic of create group of 5 bits and python part is the same.</p>

<p>Another question: can I create these address (P2WPKH and P2SH native) from bitcoin-cli?</p>

CC BY-SA 4.0
2020-03-27T22:13:03.263Z
The data encoded using 8->5 bit conversion is not the entire scriptPubKey, just the witness program itself (=the 32 bytes coming out of SHA256). You then prefix it with a 'q' (for witness version 0).
Pieter Wuille
CC BY-SA 4.0
2020-03-27T22:19:45.897Z
thanks for reply, but I don't understand sorry. Now I use Public key to generate group of 5 bits. You mean use the SHA256 of `SCRIPTPUBKEY`? In that way I have the same problem, I don't receive the right result. thanks
monkeyUser
CC BY-SA 4.0
2020-03-27T22:24:57.243Z
You're converting the entire scriptPubKey to groups of 5 bits. You're only supposed to convert the script hash (this is also the case with P2WPKH, except with ripemd160(sha256(pubkey)) instead of sha256(script)).
Pieter Wuille
CC BY-SA 4.0
2020-03-27T22:32:46.267Z
Script is `SCRIPT=210279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798AC` script hash is `1863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262` scriptPubKey is: `00201863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262`

Then I convert to base2 the scripthash `1863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262` but I can't get the right result
monkeyUser
CC BY-SA 4.0
2020-03-27T22:36:34.037Z
Ok, that sounds correct. I was confused by your first "00000" 5-bit group that came out. I don't have time right now to go into more detail, but perhaps someone else will.
Pieter Wuille
CC BY-SA 4.0
2020-03-28T08:12:21.970Z
Your mistake is in bech32 encoding (the part of the code you removed from your post). The hash being `1863...` makes your bits be like this (first item is witver) `00000 00011 00001 10001 1...` which are `0,3,1,17,...` as integers that makes chars as `q,r,p,3,...` that is the same as correct address `tb1qrp3...`
Coding Enthusiast
CC BY-SA 4.0
2020-03-28T15:05:13.603Z
@CodingEnthusiast thanks for your reply, I updated my question. I don't understand why I should to have 00011, i need to add just two zeros at the beginning. Thanks !
monkeyUser
<segregated-witness><witness-data><p2wsh>
Generate P2WSH native
monkeyUser
# Generate P2WSH native

(Asked by: username_0 on 2020-03-27)

I want to create P2WSH native like <https://en.bitcoin.it/wiki/BIP_0173>.
I have already a script to generate P2WPKH and it works, thank the python part and re-arrange group byte works.

I read that witnessScript (scriptPubKey) is hash of SHA256 without RIPEMD160.
Below a little bit of my code.

```
PB=0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798

#REDEEM SCRIPT <Public Key> OP_CHECKSIG
SCRIPT=210279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798AC

#SCRIPT HASH
$ printf $SCRIPT | xxd -r -p | openssl sha256| sed 's/^.* //'
1863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262

Convert scripthash to base 2

```

> 11000 01100 01100 01010 00011 11000 00101 00110 00101 00010 11001 10100 00000 01001 01111 01000 11001 00100 00000 11001 10101 01101
> 10110 10000 10011 01101 10010 01100 00101 01100 11110 00110 01101
> 01001 10100 10011 11010 00011 01110 00110 00110 00110 01010 01011
> 00000 01001 00100 00001 10010 01100 010

I need to add two zero at the beginning in order to Re-arrange those bits into groups of 5

> 00110 00011 00011 00010 10000 11110 00001 01001 10001 01000 10110
> 01101 00000 00010 01011 11010 00110 01001 00000 00110 01101 01011
> 01101 10100 00100 11011 01100 10011 00001 01011 00111 10001 10011
> 01010 01101 00100 11110 10000 11011 10001 10001 10001 10010 10010
> 11000 00010 01001 00000 01100 10011 00010

Add witness program

> 00000 00110 00011 00011 00010 10000 11110 00001 01001 10001 01000 10110
> 01101 00000 00010 01011 11010 00110 01001 00000 00110 01101 01011
> 01101 10100 00100 11011 01100 10011 00001 01011 00111 10001 10011
> 01010 01101 00100 11110 10000 11011 10001 10001 10001 10010 10010
> 11000 00010 01001 00000 01100 10011 00010

Convert each bits to base10

```
0, 6, 3, 3, 2, 16, 30, 1, 9, 17, 8, 22, 13, 0, 2, 11, 26, 6, 9, 0, 6, 13, 11, 13, 20, 4, 27, 12, 19, 1, 11, 7, 17, 19, 10, 13, 4, 30, 16, 27, 17, 17, 17, 18, 18, 24, 2, 9, 0, 12, 19, 2    

```

Create the checksum with python code

```
15
29
21
28
10
6

```

my result is:

```
tb1qxrrzs7pf3gkdqzt6xfqxdtd5ymvnpt83n2dy7sm333jjczfqvnz0a4u2x

```

but the result in BIP 0173 is

```
tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7

```

I use the same script to generate P2WPKH that you can find in BIP\_173 and it works. Of course I change Public key with public key hash, but the logic of create group of 5 bits and python part is the same.

Another question: can I create these address (P2WPKH and P2SH native) from bitcoin-cli?

**Tags:** segregated-witness, witness-data, p2wsh

> **Comments:**
> **username_1**: The data encoded using 8->5 bit conversion is not the entire scriptPubKey, just the witness program itself (=the 32 bytes coming out of SHA256). You then prefix it with a 'q' (for witness version 0).  
> **username_0**: thanks for reply, but I don't understand sorry. Now I use Public key to generate group of 5 bits. You mean use the SHA256 of `SCRIPTPUBKEY`? In that way I have the same problem, I don't receive the right result. thanks  
> **username_1**: You're converting the entire scriptPubKey to groups of 5 bits. You're only supposed to convert the script hash (this is also the case with P2WPKH, except with ripemd160(sha256(pubkey)) instead of sha256(script)).  
> **username_0**: Script is `SCRIPT=210279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798AC` script hash is `1863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262` scriptPubKey is: `00201863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262`  Then I convert to base2 the scripthash `1863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262` but I can't get the right result  
> **username_1**: Ok, that sounds correct. I was confused by your first "00000" 5-bit group that came out. I don't have time right now to go into more detail, but perhaps someone else will.  
> **username_2**: Your mistake is in bech32 encoding (the part of the code you removed from your post). The hash being `1863...` makes your bits be like this (first item is witver) `00000 00011 00001 10001 1...` which are `0,3,1,17,...` as integers that makes chars as `q,r,p,3,...` that is the same as correct address `tb1qrp3...`  
> **username_0**: @username_2 thanks for your reply, I updated my question. I don't understand why I should to have 00011, i need to add just two zeros at the beginning. Thanks !  

---

## 1 answers

### Answer by username_2 on 2020-03-28. Score: 2 | Accepted answer

Bech32 encoding, apart from the checksum, is a simple matter of converting base-256 (8-bits) to base-32 (5-bits). Base-256 is the byte array (octet string) that you get from a hash function. Only focusing on first 3 bytes of the hash:

```
as hex    = 0x18     0x63     0x14 
as bytes  = 24       99       20 
as binary = 00011000 01100011 00010100 

```

In order to convert the above base-256 (8-bits) input to base-32 (5-bits) we start from the most significant bit and select 5 bits at a time until we run out.

```
12345123 45123451 23451234 ...
00011000 01100011 00010100
(00011) (00001) (10001) (10001) (0100 ...

```

For a bech-32 *address* there is an extra step here **after the base conversion is done**. That step is to append of the "witness version" to the beginning of this group as an already converted value in base-32 (since witness version is defined from 0 to 16 inclusive it is already in range).

```
[00000] (00011) (00001) (10001) (10001) (0100 ...

```

This final result can be converted to an array of *numbers* that are between 0 and 31

```
0, 3, 1, 17, 17

```

To convert this "number" array to human readable format we print the corresponding character from the bech32 charset (`qpzry9x8gf2tvdw0s3jn54khce6mua7l`)

```
0->q, 3->r, 1->p, 17->3, 17->3 ...

```

P.S. There is a checksum calculation that I skipped to keep it simple but it is just another appended set of 5-bit values at the *end* of what we have in last step.

> **Comments:**
> **username_0**: oh thanks, I just convert SHA256 digest into base2. it's not enough? ```SCRIPT_HASH=`printf $SCRIPT | xxd -r -p | openssl sha256| sed 's/^.* //'``` Then convert to base2```echo "ibase=16; obase=2; $(echo $SCRIPT_HASH | tr '[:lower:]' '[:upper:]') " | bc  | sed 's/\\//g' | tr -d '\n' > base2.txt```  
> **username_0**: that command is not correct echo `'ibase=16; obase=2; 18' | bc`? I use the same logic and script for P2WPKH and same logic to calculate Seed phrase. thanks again  
> **username_0**: I can generate P2WPKH without a problem with same logic, even your post in bitcoin talk (https://bitcointalk.org/index.php?topic=4992632.0). the P2WSH logic about Base2 is different?  
> **username_2**: I can't understand the code you posted so I can't tell which part of it is wrong. But you may be having a bug that works with 20 bytes input but not with 32. There is a padding involved when converting bits (20 byte = 160 bit % 5 = *0* but 32 byte = 256 bit % 5 = *1*).  
> **username_0**: Enthusuast. Thanks for your time, it's very funny because with 20 byte it works. Anyway maybe I find a bug, but I have a new problem with checksum (in 20 byte is ok obviously)  

---

