Android Question Create checksum for entropy

Livio F

Member
Licensed User
Longtime User
Hello.
I'm trying to create a checksum of a fixed entropy, the same as the one calculated in the tutorial:
https://learnmeabitcoin.com/technical/mnemonic. The tutorial teaches us in ruby, so I need to convert from ruby to java:
For this, I am using the website: https://algodaily.com/convert/ruby/java.
The problem is that I'm not getting the same result as the tutorial checksum.

Do you know what could be wrong?

1707697780580.png

my example is calculating 01, and the tutorial calculates 00.
1707697885815.png


ruby:
Create checksum:
# ----------------------
# 2. Entropy to Mnemonic
# ----------------------
entropy = "1010110111011000110010010010111001001011001001010110001011100001"

# 1. Create checksum
require 'digest'
size = entropy.length / 32 # number of bits to take from hash of entropy (1 bit checksum for every 32 bits entropy)
sha256 = Digest::SHA256.digest([entropy].pack("B*")) # hash of entropy (in raw binary)
checksum = sha256.unpack("B*").join[0..size-1] # get desired number of bits
puts "checksum: #{checksum}"

java:
import java.security.MessageDigest;
import java.nio.charset.StandardCharsets;
import java.math.BigInteger;

    public static String genchecksum(String mEntropy) throws Exception {
        String entropy = mEntropy;

        // 1. Create checksum
        int size = entropy.length() / 32; // Number of bits to take from hash of entropy (1 bit checksum for every 32 bits entropy)
      
        BA.Log("size: " + size);
      
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        byte[] sha256 = digest.digest(new BigInteger(entropy, 2).toByteArray()); // Hash of entropy (in raw binary)

        BA.Log("byte: " + sha256);

        String binarySha256 = new BigInteger(1, sha256).toString(2);
        // Ensure leading 0's are not lost
        while (binarySha256.length() < sha256.length * 8) {
            binarySha256 = "0" + binarySha256;
        }
        String checksum = binarySha256.substring(0, size); // Get desired number of bits
        return checksum;
    }


my project test attach
 

Attachments

  • seedtst.zip
    9.9 KB · Views: 26
Solution
drgottjr, it didn't work for other entropies,
but as you warned, replace the biginteger code with one generated by https://algodaily.com/convert/ruby/java.
And it seems to work for other entropies too.

Thank you, your warning helped a lot.

B4X:
byte[] sha256 = digest.digest(toByteArray(entropy)); // hash of entropy (in raw binary)

public static byte[] toByteArray(String s) {
        int len = s.length();
        byte[] data = new byte[len / 8];
        for (int i = 0; i < len; i += 8) {
            data[i / 8] = (byte) Integer.parseInt(s.substring(i, i + 8), 2);
        }
        return data;
        }

drgottjr

Expert
Licensed User
Longtime User
biginteger is not my favorite area, but i think the problem here is this:
B4X:
        byte[] sha256 = digest.digest(new BigInteger(entropy, 2).[B]toByteArray()[/B]); // Hash of entropy (in raw binary)

biginteger converttobytearray() gives you a 9-byte result. it includes a leading sign. check biginteger javadoc. i think you want 8.

if you break things down a bit:
B4X:
        BigInteger bi = new BigInteger(entropy, 2);
        byte[] step1 = bi.toByteArray();
        
        byte[] step2 = new byte[8];
        java.lang.System.arraycopy(step1,1,step2,0,8);

        byte[] sha256 = digest.digest( step2 ); // Hash of entropy (in raw binary)
        ' ... continue

and proceed from there, you end up with checksum "00". anyway, i do.
 
Upvote 1

Livio F

Member
Licensed User
Longtime User
drgottjr, it didn't work for other entropies,
but as you warned, replace the biginteger code with one generated by https://algodaily.com/convert/ruby/java.
And it seems to work for other entropies too.

Thank you, your warning helped a lot.

B4X:
byte[] sha256 = digest.digest(toByteArray(entropy)); // hash of entropy (in raw binary)

public static byte[] toByteArray(String s) {
        int len = s.length();
        byte[] data = new byte[len / 8];
        for (int i = 0; i < len; i += 8) {
            data[i / 8] = (byte) Integer.parseInt(s.substring(i, i + 8), 2);
        }
        return data;
        }
 
Upvote 0
Solution

drgottjr

Expert
Licensed User
Longtime User
i liked the sound of "entropy". it sounded like a disease against which you could be inoculated before travelling abroad.

based on the "tutorial" referred to in the first link, i fashioned a small library to handle the whole process: generate entropy, create the mnemonic phrase, create the seed. i wrote it with b4j non-gui in mind.

declare the Gentropy class and run the appropriate methods:
genGentropy - create a 128-bit entropy
genMnemonic - create the mnemonic sentence from that entropy.
genSeed - create the seed from the mnemonic sentence...

you can either generate your own entropy or use some generated elsewhere. genMnemonic accepts either. if you use entropy generated elsewhere, it can be 64, 128 or 256 bits. the hovering tool reports what each method does.

the file from which the mnemonic sentence is created is the "official" english version. there are several others. the library is mostly a proof of concept, so i used the
english version.

in the wild, seed creation offers several options. i went with a simple model. if somebody actually wanted to use the library to generate his bitcoin wallet credentials, he might want to rethink that.

i didn't perform any bullet-proofing; if you provide your own garbage entropy to see if you can provoke a crash, you might succeed.

if the thing is useful, i can probably be coaxed into making it worthy of use.

B4X:
    Dim gentropy As Gentropy
    Dim entropy As String = gentropy.genGentropy
    Log(entropy)
   
    ' OR USE ENTROPY CREATED ELSEWHERE:
    Dim entropy As String = "11111101111011011110011100111010010011111100001110011000001111110000011011001110001010100011101001000011010100100100000001000000"
   
    Dim mnemonicsentence As String = gentropy.genMnemonic( entropy )
    Log("mnemonic sentence: " & mnemonicsentence)
    Dim seed As String = gentropy.genSeed( mnemonicsentence )
    Log(seed)
 

Attachments

  • gentropy.zip
    22.9 KB · Views: 31
  • gentropy.png
    gentropy.png
    27.8 KB · Views: 26
Last edited:
Upvote 0
Top