<p>Using binary will be more clear.</p>
<pre><code>Seed = ENT + CS
</code></pre>
<p>There is 1 bit of checksum for every 32 bits of entropy.</p>
<pre><code>Seed = ENT + ENT/32
</code></pre>
<p>if ENT (ENT must be divisible by 32) is 192 bits in length</p>
<pre><code>CS = 192/32 = 6 bits
</code></pre>
<p>Take the first 6 bits from sha2sum, and add them to the end of your ENT</p>
<hr />
<p>Additional: Why number of words is required to be [12, 15, 18, 21, 24]?</p>
<p>Each words is 11 bits</p>
<pre><code>Seed = ENT + CS = 11 * words 

ENT + ENT/32 = 11 * words
&lt;=&gt; 32 * ENT + ENT = 32 * 11 *words
&lt;=&gt; 33 * ENT = 32 * 11 * words
&lt;=&gt; 3 * ENT = 32 * words
&lt;=&gt; ENT = 32 * words / 3
</code></pre>
<p>so the number of words needs to be divisible by 3 to make ENT an integer</p>

CC BY-SA 4.0
2024-03-27T04:24:21.210Z
2024-03-27T04:24:21.210Z
X Digital
<p>I'm trying to understand the logic of generating a valid BIP-39 seed phrase. I have read the BIP-39 and trying to implement the section <a href="https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki#generating-the-mnemonic" rel="nofollow noreferrer">Generating the mnemonic</a> step by step. I have the following Crystal code that works very well for a 256-bit seed I found in the answer to: <a href="https://bitcoin.stackexchange.com/a/75314/6441">How to generate a valid hash for a bip39 seed phrase?</a></p>
<pre><code># First, an initial entropy of ENT bits is generated.
entropy = &quot;87c1b129fbadd7b6e9abc0a9ef7695436d767aece042bec198a97e949fcbe14c&quot;
# =&gt; &quot;87c1b129fbadd7b6e9abc0a9ef7695436d767aece042bec198a97e949fcbe14c&quot;

# A checksum is generated by taking the first ENT / 32 bits of its SHA256 hash.
sha2sum = OpenSSL::Digest.new(&quot;SHA256&quot;).update(entropy.hexbytes).final.hexstring
# =&gt; &quot;0dc811788c7e02c32b9c4b3586baf58ca27f74330c92d661042b19faa6c7e9f2&quot;

# the checksum length (CS): 2 (hex) := 8 (bits)
checksum_length_hex = 2
# =&gt; 2

checksum = sha2sum[0, checksum_length_hex]
# =&gt; &quot;0d&quot;

# This checksum is appended to the end of the initial entropy.
entropy_checksummed = entropy + checksum
# =&gt; &quot;87c1b129fbadd7b6e9abc0a9ef7695436d767aece042bec198a97e949fcbe14c0d&quot;
</code></pre>
<p>This works, as I said and my code is able to generate the correct indices for the words required, and the resulting phrase matches with the one provided in the other thread.</p>
<p>My problem is, however, how do we manage the <code>checksum_length_hex</code> for entropies of 160, 192, and 224 bits? As I said, my code works for 256 bit with <code>checksum_length_hex</code> of <code>2</code> and it also works for 128 bit with a length of <code>1</code>.</p>
<p>But how do I deal with the cases in between? I cannot create a prefix of <code>1.2</code>. I was thinking of taking the checksum prefix in pure bits (e.g., 5 bits for 160 entropy) and eventually got only gibberish results. The following table is taken directly from BIP-39:</p>
<pre><code># |  ENT  | CS | ENT+CS |  MS  |
# +-------+----+--------+------+
# |  128  |  4 |   132  |  12  |
# |  160  |  5 |   165  |  15  |
# |  192  |  6 |   198  |  18  |
# |  224  |  7 |   231  |  21  |
# |  256  |  8 |   264  |  24  |
</code></pre>
<p>How do I properly compute BIP-39 checksum bytes of sizes 5, 6, and 7 for entropies of 160, 192, and 224?</p>

CC BY-SA 4.0
2021-10-28T23:31:51.607Z
As you mentioned you need to convert it to binary instead of hex and only take the last 5 out of 165 bits
Mike D
CC BY-SA 4.0
2021-10-29T21:54:55.327Z
Thanks. I spent more time manipulating the binary representation and managed to get this to work. Feel free to pour this into an answer.
q9f
<mnemonic-seed><bip><ruby><checksum>
How to properly compute the BIP39 checksum bytes?
q9f
# How to properly compute the BIP39 checksum bytes?

(Asked by: username_0 on 2021-10-28)

I'm trying to understand the logic of generating a valid BIP-39 seed phrase. I have read the BIP-39 and trying to implement the section [Generating the mnemonic](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki#generating-the-mnemonic) step by step. I have the following Crystal code that works very well for a 256-bit seed I found in the answer to: [How to generate a valid hash for a bip39 seed phrase?](https://bitcoin.stackexchange.com/a/75314/6441)

```
# First, an initial entropy of ENT bits is generated.
entropy = "87c1b129fbadd7b6e9abc0a9ef7695436d767aece042bec198a97e949fcbe14c"
# => "87c1b129fbadd7b6e9abc0a9ef7695436d767aece042bec198a97e949fcbe14c"

# A checksum is generated by taking the first ENT / 32 bits of its SHA256 hash.
sha2sum = OpenSSL::Digest.new("SHA256").update(entropy.hexbytes).final.hexstring
# => "0dc811788c7e02c32b9c4b3586baf58ca27f74330c92d661042b19faa6c7e9f2"

# the checksum length (CS): 2 (hex) := 8 (bits)
checksum_length_hex = 2
# => 2

checksum = sha2sum[0, checksum_length_hex]
# => "0d"

# This checksum is appended to the end of the initial entropy.
entropy_checksummed = entropy + checksum
# => "87c1b129fbadd7b6e9abc0a9ef7695436d767aece042bec198a97e949fcbe14c0d"

```

This works, as I said and my code is able to generate the correct indices for the words required, and the resulting phrase matches with the one provided in the other thread.

My problem is, however, how do we manage the `checksum_length_hex` for entropies of 160, 192, and 224 bits? As I said, my code works for 256 bit with `checksum_length_hex` of `2` and it also works for 128 bit with a length of `1`.

But how do I deal with the cases in between? I cannot create a prefix of `1.2`. I was thinking of taking the checksum prefix in pure bits (e.g., 5 bits for 160 entropy) and eventually got only gibberish results. The following table is taken directly from BIP-39:

```
# |  ENT  | CS | ENT+CS |  MS  |
# +-------+----+--------+------+
# |  128  |  4 |   132  |  12  |
# |  160  |  5 |   165  |  15  |
# |  192  |  6 |   198  |  18  |
# |  224  |  7 |   231  |  21  |
# |  256  |  8 |   264  |  24  |

```

How do I properly compute BIP-39 checksum bytes of sizes 5, 6, and 7 for entropies of 160, 192, and 224?

**Tags:** mnemonic-seed, bip, ruby, checksum

> **Comments:**
> **username_1**: As you mentioned you need to convert it to binary instead of hex and only take the last 5 out of 165 bits  
> **username_0**: Thanks. I spent more time manipulating the binary representation and managed to get this to work. Feel free to pour this into an answer.  

---

## 1 answers

### Answer by username_2 on 2024-03-27. Score: 0

Using binary will be more clear.

```
Seed = ENT + CS

```

There is 1 bit of checksum for every 32 bits of entropy.

```
Seed = ENT + ENT/32

```

if ENT (ENT must be divisible by 32) is 192 bits in length

```
CS = 192/32 = 6 bits

```

Take the first 6 bits from sha2sum, and add them to the end of your ENT

---

Additional: Why number of words is required to be [12, 15, 18, 21, 24]?

Each words is 11 bits

```
Seed = ENT + CS = 11 * words 

ENT + ENT/32 = 11 * words
<=> 32 * ENT + ENT = 32 * 11 *words
<=> 33 * ENT = 32 * 11 * words
<=> 3 * ENT = 32 * words
<=> ENT = 32 * words / 3

```

so the number of words needs to be divisible by 3 to make ENT an integer


---

