# How to properly compute the BIP39 checksum bytes?

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 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?

``````# First, an initial entropy of ENT bits is generated.

# 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
``````

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?

• As you mentioned you need to convert it to binary instead of hex and only take the last 5 out of 165 bits Commented Oct 28, 2021 at 23:31
• 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
Commented Oct 29, 2021 at 21:54

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