Author

Topic: Creating a Bitcoin Core seed using base 6 number (Dice roll) (Read 316 times)

legendary
Activity: 2870
Merit: 7490
Crypto Swap Exchange
you should use a debiasing procedure like the one in the codex32 booklet: https://www.secretcodex32.com/
That's an interesting approach for dice, and one I had not seen before. It is essentially the same basis as the Von Neumann debiasing algorithm for coins I linked to earlier in the thread, where you flip twice and discard the result if the two flips are the same, but adapted for dice.

Having said that, it's also far more complicated. I like to keep things simple and would just stick to coin flips.

Relevant discussion thread, https://bitcointalksearch.org/topic/codex32-5440916. Anyway, i also agree Codex32 is rather complicated.

I saw Andrew Poelstra talking about this on a "Bitcoin Layer" podcast recently. I have casino grade dice, with the sharp edges. Are these really biased? I assumed the casinos would demand some controls during manufacturing to try un-bias the dice.

Unless you're an expert, there's no way you could know whether the company actually create dice with casino grade / reduced biased. It's not rare occurrence for company to exaggerate or even lying about their product standard/capability.
legendary
Activity: 2268
Merit: 18748
you should use a debiasing procedure like the one in the codex32 booklet: https://www.secretcodex32.com/
That's an interesting approach for dice, and one I had not seen before. It is essentially the same basis as the Von Neumann debiasing algorithm for coins I linked to earlier in the thread, where you flip twice and discard the result if the two flips are the same, but adapted for dice.

Having said that, it's also far more complicated. I like to keep things simple and would just stick to coin flips.

Are these really biased?
You would never know unless you rolled them thousands of times and performed some statistical analysis on the results. Safer to just assume they are and use a debiasing method.

And I would roll it 256 times anyway, and treat each value as a single zero or one, to avoid modulo bias.
You still need to correct for physical bias, which is far more simple with a coin than with a die.

Flip the coin twice:
HT - 0
TH - 1
HH or TT - discard

Repeat until you have 256 bits. No matter how biased your coin is, you'll always get a completely random result.
copper member
Activity: 906
Merit: 2258
Quote
Code:
1 => 00
2 => 01
3 => 10
4 => 11
5 => 0
6 => 1
And introduce modulo bias? Better take odd numbers as zeroes, and even numbers as ones, or do something similar.

Edit:
Quote
99*6 is 594 bits
I guess rolling a dice once does not provide you 2^6=64 combinations. And I would roll it 256 times anyway, and treat each value as a single zero or one, to avoid modulo bias. Also, then you don't need additional tricks to get some 256-bit number out of that. Optionally, you can just collect those 99 numbers, write them as decimal numbers, and execute sha256sum on that string, it would be also sufficient, but personally I prefer treating each roll as a binary number.
legendary
Activity: 1512
Merit: 7340
Farewell, Leo
So you should either roll much more than needed and sha256 the result or you should use a debiasing procedure like the one in the codex32 booklet: https://www.secretcodex32.com/
Even if the dice is very biased, throwing it 99 times, as xx879 says, will suffice. In this post, I demonstrate that even if there is a 50% chance of getting a 6 (and 10% for each 1, 2, 3, 4, 5), it will still produce 216 bits of entropy. As a disclaimer, I had just applied Shannon's equation, and I'm by no means an expert in that branch of math.

I saw Andrew Poelstra talking about this on a "Bitcoin Layer" podcast recently. I have casino grade dice, with the sharp edges. Are these really biased? I assumed the casinos would demand some controls during manufacturing to try un-bias the dice.
All physical dice are biased to an extent. I think casino dice are known for approaching perfection.
newbie
Activity: 12
Merit: 13
I saw Andrew Poelstra talking about this on a "Bitcoin Layer" podcast recently. I have casino grade dice, with the sharp edges. Are these really biased? I assumed the casinos would demand some controls during manufacturing to try un-bias the dice.
staff
Activity: 4284
Merit: 8808
If you're going through all the trouble to generate a key using dice you should be aware that all real dice are biased to some degree.  So you should either roll much more than needed and sha256 the result or you should use a debiasing procedure like the one in the codex32 booklet: https://www.secretcodex32.com/
newbie
Activity: 12
Merit: 13
I will not be able to update my version of Bitcoin Core beyond v23. I will have to use "legacy" wallet types only for my use-case.

Soon there should be a mechanism which allows you to specify your own hdseeds for descriptor wallets after they are created, which should reduce the need for the legacy wallet format. It's a work-in-progress I believe on github, but it's an annoying issue which affects other things like dumping private keys and performing manual derivation and stuff.

I think I know the issue you are talking about, I saw it was closed due to inactivity  Undecided
legendary
Activity: 1568
Merit: 6660
bitcoincleanup.com / bitmixlist.org
I will not be able to update my version of Bitcoin Core beyond v23. I will have to use "legacy" wallet types only for my use-case.

Soon there should be a mechanism which allows you to specify your own hdseeds for descriptor wallets after they are created, which should reduce the need for the legacy wallet format. It's a work-in-progress I believe on github, but it's an annoying issue which affects other things like dumping private keys and performing manual derivation and stuff.
newbie
Activity: 12
Merit: 13
I asked an LLM to modify your python code, so that it outputs a master xpriv:

Code:
import hashlib
import base58

def master_xprv_from_seed(seed_hex, network_byte=0x0488ADE4):
    # convert seed from hex to bytes
    seed_bytes = bytes.fromhex(seed_hex)

    # add network byte prefix
    extended_key = bytes([network_byte]) + seed_bytes

    # checksum = first 4 bytes of sha256(sha256(key))
    checksum = hashlib.sha256(hashlib.sha256(extended_key).digest()).digest()[:4]

    # append the checksum to the extended key
    extended_key += checksum

    # convert to base58
    xprv = base58.b58encode(extended_key)

    return xprv.decode('utf-8')

if __name__ == "__main__":
    seed_hex = input("Enter the seed in hex format: ")

    try:
        xprv = master_xprv_from_seed(seed_hex)
        print("Master xprv:", xprv)
    except ValueError:
        print("Invalid seed input.")

And then to import the master private key into Bitcoin Core, I would:

Code:
importdescriptors '[{"desc": "wpkh([master_xprv/84'/0'/0']/0/*)", "timestamp": "now", "range": [0, 1000], "watchonly": true, "label": "YourLabel"}]'

I assume "wpkh" and "p2wpkh" are arbitrary decisions in this case, but the decision will affect all future addresses that are generated.

I would do all of this work on an offline machine. Then I would use
Code:
listdescriptors
to get the xpub, and then on the online machine I would
Code:
importmulti '[{"desc":"pkh([Your xpub key])","timestamp":"now","range":[0,100],"watchonly":true,"label":"[Label for the wallet]"}]'

Is that right?
legendary
Activity: 2268
Merit: 18748
I will not be able to update my version of Bitcoin Core beyond v23.
Not wise to lock yourself to an old version. Although legacy wallets still work fine in v25, by the way.

I will have to use "legacy" wallet types only for my use-case.
You can turn your custom entropy in to a master private key you can import in to a descriptors wallet as I explained above, but you won't be able to do it without additional software.

Alternatively, have you considered using something like Electrum or Sparrow instead? You can turn your custom entropy in to a BIP39 seed phrase and then import that to these wallets offline, and then export the master public key from your offline wallet to move to your other machine and create your watch only wallet. Your Electrum or Sparrow watch only wallet can be synced using your own node.
newbie
Activity: 12
Merit: 13
I should better explain my use case:

I would like to create my own seed by using dice throws. When I have a 99 digit base 6 number, I want to type that into Bitcoin Core on an offline machine/live os. Then I want to take the XPUB that is created, and transfer it to an online machine running Bitcoin Core as "watch only". Then I can create new receiving addresses on the online machine, which I will also use to create PSBTs.

I don't mind using a simple script or two if absolutely necessary, but I prefer to only use Bitcoin Core for security reasons.


It seems this is simply not going to be possible. From Bitcoin Core v23:

the legacy wallet type is being deprecated and support for creating and opening legacy wallets will be removed in the future

I will not be able to update my version of Bitcoin Core beyond v23. I will have to use "legacy" wallet types only for my use-case.

- createwallet "wallet_name" ( disable_private_keys blank "passphrase" avoid_reuse descriptors load_on_startup external_signer )

descriptors will have to be set to false.

Then I can use:
- sethdseed ( newkeypool "seed" )

I will set newkeypool to true, and the "seed" is the WIF private address that is generated by the python script provided by BlackHatCoiner.

After that I can use:

- getnewaddress on offline machine, then save this to text file and import into bitcoin core on online machine using
importaddress "address" ( "label" rescan p2sh )

And then, when I am ready to spend:

- estimatesmartfee/createpsbt on server (to build a transaction with current fees)
- save the transaction in a text file, take to offline machine
- walletprocesspsbt on offline machine, save to text file and take to online machine
- broadcast transaction

Is this generally correct?

This way I have a paper copy of my original seed (a random 99 digit number in base 6), I have an offline machine and electronic copies of an encrypted wallet.dat file with private keys, and I have an online machine which never sees private keys but allows access to the bitcoin network.
newbie
Activity: 12
Merit: 13
I understand your use case better now. You want to create a Bitcoin wallet using a manually generated seed, which you'll enter into Bitcoin Core on an offline machine, and then use the XPUB to create a "watch-only" wallet on an online machine. This approach can enhance security.

Here's a high-level overview of the process:

Generate Seed: Manually generate a 99-digit base-6 number using dice throws, ensuring it's highly random.
Offline Machine:
Install Bitcoin Core on an offline machine.
Enter the seed to create a wallet.
Note down the XPUB (extended public key).
Online Machine:
Install Bitcoin Core on an online machine.
Import the XPUB from the offline wallet as a "watch-only" wallet.
Create new receiving addresses on the online machine for transactions and PSBTs.
You can follow these steps manually within the Bitcoin Core GUI, which is designed to handle these tasks securely. No additional scripts should be necessary for this process, as Bitcoin Core provides the needed functionality for generating and importing wallets.

Remember to keep your offline machine entirely disconnected from the internet during the initial setup to maintain security. Additionally, ensure you have backups of your seed in case of data loss or hardware failure.

hello chatgpt 3.5
legendary
Activity: 1568
Merit: 6660
bitcoincleanup.com / bitmixlist.org
I should better explain my use case:

I would like to create my own seed by using dice throws. When I have a 99 digit base 6 number, I want to type that into Bitcoin Core on an offline machine/live os. Then I want to take the XPUB that is created, and transfer it to an online machine running Bitcoin Core as "watch only". Then I can create new receiving addresses on the online machine, which I will also use to create PSBTs.

I don't mind using a simple script or two if absolutely necessary, but I prefer to only use Bitcoin Core for security reasons.

Here's the thing: First you have to convert that 99 digit base 6 number into a format that Bitcoin Core understands since it can't just take any string. 99*6 is 594 bits, divide that into 8 and it's slightly over 74 bytes, i.e. more than you'll need for the hdseed since as the others said, it is represented as a private key - those have 256 bits.

And maybe it's not the best idea to use the digits directly, after all, they have no special meaning besides entropy, but maybe you can use something like this method: https://crypto.stackexchange.com/a/6177/94542

Code:
1 => 00
2 => 01
3 => 10
4 => 11
5 => 0
6 => 1

The numbers on the right are binary bits you add to the right of the sequence that you're making (just as you would with the dice). Then you can group sequences of 4 bits into hex characters once you have 256 bits.
newbie
Activity: 12
Merit: 13
I should better explain my use case:

I would like to create my own seed by using dice throws. When I have a 99 digit base 6 number, I want to type that into Bitcoin Core on an offline machine/live os. Then I want to take the XPUB that is created, and transfer it to an online machine running Bitcoin Core as "watch only". Then I can create new receiving addresses on the online machine, which I will also use to create PSBTs.

I don't mind using a simple script or two if absolutely necessary, but I prefer to only use Bitcoin Core for security reasons.
newbie
Activity: 12
Merit: 13
I would like to use "sethdseed" so all future pub and priv keys are derived from the seed I provided. Can I use the "importdescriptors" command to do that?
No. As BlackHatCoiner has explained above, sethdseed command is only compatible with non-descriptor wallets.

If you want to use the importdescriptor command to create an HD wallet, then your descriptor will need to include a master private key (xprv), rather than a WIF key. So you will need to use your manually generated entropy to generate an xprv first.

Do you know how I could do this?

I see that somebody was working on this, but I guess it was not completed:
https://github.com/bitcoin/bitcoin/pull/8735
legendary
Activity: 2268
Merit: 18748
I would like to use "sethdseed" so all future pub and priv keys are derived from the seed I provided. Can I use the "importdescriptors" command to do that?
No. As BlackHatCoiner has explained above, sethdseed command is only compatible with non-descriptor wallets.

If you want to use the importdescriptor command to create an HD wallet, then your descriptor will need to include a master private key (xprv), rather than a WIF key. So you will need to use your manually generated entropy to generate an xprv first.
newbie
Activity: 12
Merit: 13
You cannot import a seed manually with sethdseed in a descriptor wallet. It has to be a legacy wallet

I am now confused by the workflow after converting the seed to a WIF private address, especially after reading this:
https://bitcoin.stackexchange.com/questions/113846/how-can-a-private-key-be-imported-to-a-descriptor-wallet

I would like to use "sethdseed" so all future pub and priv keys are derived from the seed I provided. Can I use the "importdescriptors" command to do that? 
newbie
Activity: 12
Merit: 13
Very nice, thank you! I wish I could use the bitcoin-cli for this, but I suppose this is the next best thing.
legendary
Activity: 1512
Merit: 7340
Farewell, Leo
Then you can import that private address into a new descriptor wallet.
You cannot import a seed manually with sethdseed in a descriptor wallet. It has to be a legacy wallet, otherwise you'll encounter the error:
[...]
Here's a quick Python program for you:
Code:
import hashlib
import base58

def private_key_to_wif(private_key_hex, network_byte=0x80):
    # convert private key from hex to bytes
    private_key_bytes = bytes.fromhex(private_key_hex)

    # add network byte prefix
    extended_key = bytes([network_byte]) + private_key_bytes

    # checksum = :4 from sha256(sha256(key))
    checksum = hashlib.sha256(hashlib.sha256(extended_key).digest()).digest()[:4]

    # append the checksum to the extended key
    extended_key += checksum

    # convert to base58
    wif = base58.b58encode(extended_key)

    return wif.decode('utf-8')

if __name__ == "__main__":
    private_key_hex = input("Enter the Bitcoin private key in hex format: ")
   
    try:
        wif = private_key_to_wif(private_key_hex)
        print("WIF:", wif)
    except ValueError:
        print("Invalid private key input.")

It takes as input a 256-bit private key, and converts it to WIF. You can create a new file, paste it there and run it with python3 file.py. Note that you must have base58 installed. To do it, run pip install base58 from the terminal.
newbie
Activity: 12
Merit: 13
Maybe it would be possible to compile only the relevant portions of the Bitcoin Core code, replacing the code which generates entropy with a simple prompt for the user,

cout << "Enter a number: ";

?
newbie
Activity: 12
Merit: 13
Entropy -> 32 byte hex -> prefix network byte -> calculate and append checksum -> encode to Base58
This is what I would like to do with Bitcoin Core.  I feel that using an additional program outside of Core (either an offline version of bitaddress.org, custom python script, etc.) to do this introduces a chance for mistakes. Do you know if this can be done with Bitcoin Core somehow?
legendary
Activity: 2268
Merit: 18748
I was wondering if there is a way to use a custom seed in Bitcoin Core v23, rather than allow the program to use the default method to try to get entropy.
Yes. Use the sethdseed command. Link: https://bitcoincore.org/en/doc/25.0.0/rpc/wallet/sethdseed/

Your custom seed has to be in the format of a WIF private key, so if you are using some manual process to generate the entropy, you'll need to convert it to WIF first. Entropy -> 32 byte hex -> prefix network byte -> calculate and append checksum -> encode to Base58.

The simplest way to use a physical process to generate a private key will be to flip a coin to achieve an unbiased 256 bit number, and then convert that hex.
newbie
Activity: 12
Merit: 13
Hello,
I was wondering if there is a way to use a custom seed in Bitcoin Core v23, rather than allow the program to use the default method to try to get entropy. At the moment I believe you need to create a random number (e.g. rolling dice), then convert it to base 6 (if not base 6 already), then input that 99 digit number into a program such as bitaddress.org to create a WIF private address and public address. Then you can import that private address into a new descriptor wallet.

Is that correct? Considering all the buzz around entropy recently it seems like it would make more sense to input a random 99 digit number directly into Bitcoin Core.
Jump to: