Bitcoin Forum
November 16, 2024, 01:50:44 PM *
News: Latest Bitcoin Core release: 28.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: [1]
  Print  
Author Topic: [BOUNTY 0.01BTC] Integer to Private key. How to generate in sequence?  (Read 3547 times)
acegilz (OP)
Full Member
***
Offline Offline

Activity: 211
Merit: 100

1ACEGiLZnZoG7KUNkMwAT8tBuJ6jsrwj5Q


View Profile
December 15, 2016, 01:58:02 AM
Last edit: December 16, 2016, 01:33:08 PM by acegilz
 #1

I am struggling to understand why the first bitcoin address generating via private key is 1EHNa6Q4Jz2uvNExL497mE43ikXhwF6kZm.

Example mentions:
https://www.palkeo.com/code/stealing-bitcoin.html
http://directory.io
I assume they call it the first address because its private key may be the first that comes out when we are start encrypting from an optic of our standard decimal system, and starting on 1 or maybe 0.

What is confusing me is that if I encrypt "1" with sha256 I get the key "c555eab45d08845ae9f10d452a99bfcb06f74a50b988fe7e48dd323789b88ee3" and that key when converting to WIF format is not the same private key as above. http://gobittest.appspot.com/PrivateKey

Please clarify what am I missing.
achow101
Moderator
Legendary
*
Offline Offline

Activity: 3542
Merit: 6886


Just writing some code


View Profile WWW
December 15, 2016, 02:26:31 AM
 #2

First of all, Sha256 is a hash function, not an encryption method. They are two very different things.

Secondly, the private keys do not translate directly to addresses, you have to do the encoding with the public keys after you derive them from the private key.

You are doing it completely and absolutely incorrectly. The process you are trying to do is called Base 58 Check Encoding. The full description is here: https://en.bitcoin.it/wiki/Base58Check_encoding

First, you have to take your private key in hex form and concatenate it with the WIF version byte, which is 0x80. You will get

Code:
0x800000000000000000000000000000000000000000000000000000000000000001

Then you perform sha256d on it (two rounds of sha256 hashing) and you get
Code:
a85aa87e9879f34d1449e35c58e64d9325733ca2efb4577e6720ec42c3625783
Note the hashing is done on the bytes represented by the hex, not the ascii characters of the hex itself.

Then you take the first 4 bytes of this hash and concatenate it to the end of the original hex string, so you get
Code:
0x800000000000000000000000000000000000000000000000000000000000000001a85aa87e

Lastly you convert it from hex format to Base 58 and you get
Code:
5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf

That is the Wallet Import Format of the private key 1.

acegilz (OP)
Full Member
***
Offline Offline

Activity: 211
Merit: 100

1ACEGiLZnZoG7KUNkMwAT8tBuJ6jsrwj5Q


View Profile
December 15, 2016, 02:56:31 AM
 #3

First of all, Sha256 is a hash function, not an encryption method. They are two very different things.

Secondly, the private keys do not translate directly to addresses, you have to do the encoding with the public keys after you derive them from the private key.

You are doing it completely and absolutely incorrectly. The process you are trying to do is called Base 58 Check Encoding. The full description is here: https://en.bitcoin.it/wiki/Base58Check_encoding

First, you have to take your private key in hex form and concatenate it with the WIF version byte, which is 0x80. You will get

Code:
0x800000000000000000000000000000000000000000000000000000000000000001

Then you perform sha256d on it (two rounds of sha256 hashing) and you get
Code:
a85aa87e9879f34d1449e35c58e64d9325733ca2efb4577e6720ec42c3625783
Note the hashing is done on the bytes represented by the hex, not the ascii characters of the hex itself.

Then you take the first 4 bytes of this hash and concatenate it to the end of the original hex string, so you get
Code:
0x800000000000000000000000000000000000000000000000000000000000000001a85aa87e

Lastly you convert it from hex format to Base 58 and you get
Code:
5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf

That is the Wallet Import Format of the private key 1.

Thank you for your patience in explaining step by step. I now understand how it works.
Best Regards Wink
acegilz (OP)
Full Member
***
Offline Offline

Activity: 211
Merit: 100

1ACEGiLZnZoG7KUNkMwAT8tBuJ6jsrwj5Q


View Profile
December 15, 2016, 03:49:06 AM
 #4

Then you perform sha256d on it (two rounds of sha256 hashing) and you get
Code:
a85aa87e9879f34d1449e35c58e64d9325733ca2efb4577e6720ec42c3625783

What is happening?

=> string = '0x800000000000000000000000000000000000000000000000000000000000000001'
=> 2.times { string = Digest::SHA256.hexdigest(string) }

irb(main):284:0> c3d128a531b3ee00caef9cbaa2fe69e1fc94de99aaa6400c73147fac147cd58e
achow101
Moderator
Legendary
*
Offline Offline

Activity: 3542
Merit: 6886


Just writing some code


View Profile WWW
December 15, 2016, 03:54:20 AM
 #5

Then you perform sha256d on it (two rounds of sha256 hashing) and you get
Code:
a85aa87e9879f34d1449e35c58e64d9325733ca2efb4577e6720ec42c3625783

What is happening?

=> string = '0x800000000000000000000000000000000000000000000000000000000000000001'
=> 2.times { string = Digest::SHA256.hexdigest(string) }

irb(main):284:0> c3d128a531b3ee00caef9cbaa2fe69e1fc94de99aaa6400c73147fac147cd58e
It is not hashed as a string. That is hashed as raw hex bytes. Additionally, do not hash the 0x, that is not actually a byte, it is just an indicator that the string is a string representing the raw hex bytes of something.

acegilz (OP)
Full Member
***
Offline Offline

Activity: 211
Merit: 100

1ACEGiLZnZoG7KUNkMwAT8tBuJ6jsrwj5Q


View Profile
December 15, 2016, 02:42:19 PM
 #6

That worked perfectly, thank you Grin


What is the correct way of generating now valid addresses (both compressed and uncompressed) from these WIF's?
It's strange how I can't find any information regarding this matter of creating private keys from integer and generate bitcoin addresses from WIF googling.
achow101
Moderator
Legendary
*
Offline Offline

Activity: 3542
Merit: 6886


Just writing some code


View Profile WWW
December 15, 2016, 03:10:31 PM
 #7

That worked perfectly, thank you Grin


What is the correct way of generating now valid addresses (both compressed and uncompressed) from these WIF's?
It's strange how I can't find any information regarding this matter of creating private keys from integer and generate bitcoin addresses from WIF googling.
You have to take your integer private key and perform the ECDSA public key derivation and get the corresponding public key. Then you hash that public key with Sha256 and then hash that hash with RIPEMD160. Then you perform Base 58 Check Encoding on the result in order to get an address.

DannyHamilton
Legendary
*
Offline Offline

Activity: 3486
Merit: 4851



View Profile
December 15, 2016, 04:50:45 PM
 #8

-snip-
It's strange how I can't find any information regarding this matter of creating private keys from integer -snip- from WIF googling.

Seriously?

I just tried a Google search on "bitcoin wif".

Here's THE TOP result, it has the exact steps listed by achow101.
https://en.bitcoin.it/wiki/Wallet_import_format

The VERY NEXT result explains that a private key is simply a 256 bit integer, and demonstrates that the integer can be represented in hexadecimal radix:
https://en.bitcoin.it/wiki/Private_key

Coding Enthusiast
Legendary
*
Offline Offline

Activity: 1043
Merit: 2818


Bitcoin and C♯ Enthusiast


View Profile WWW
December 15, 2016, 05:57:59 PM
 #9

Just FYI in the link Danny gave this: 0C28FCA386C7A227600B2FE50B7CAE11EC86D3BF1FBE471BE89827E19D72AA1D is your number (integer) but in another format (hex) and if you convert it to a number it is this number: 5500171714335001507730457227127633683517613019341760098818554179534751705629 (I used BigInteger Structure in .Net framework)

Projects List+Suggestion box
Donate: 1Q9s or bc1q
|
|
|
FinderOuter(0.20.0)Ann-git
Denovo(0.7.0)Ann-git
Bitcoin.Net(0.26.0)Ann-git
|
|
|
BitcoinTransactionTool(0.11.0)Ann-git
WatchOnlyBitcoinWallet(3.2.1)Ann-git
SharpPusher(0.12.0)Ann-git
acegilz (OP)
Full Member
***
Offline Offline

Activity: 211
Merit: 100

1ACEGiLZnZoG7KUNkMwAT8tBuJ6jsrwj5Q


View Profile
December 15, 2016, 07:51:06 PM
Last edit: December 15, 2016, 08:35:18 PM by acegilz
 #10

Ok, I have been trying to follow this ruby tutorial and trying to get the address #1 but it's not really being easy...
http://royalforkblog.github.io/2014/07/31/address-gen/


Code:
number = '800000000000000000000000000000000000000000000000000000000000000001'
      string = number
      bytes = [string].pack('H*') #this converts to hex bytes
      sha1 = Digest::SHA256.digest bytes
      sha2 = Digest::SHA256.hexdigest sha1

      bytes= sha2[0...8]
      string = string+bytes

private_key = encode_base58(string)

This is working Smiley

But now the second part of generating the address is where I'm struggling

Code:

curve = ECDSA::Group::Secp256k1
pub_key = curve.generator.multiply_by_scalar(sha1.to_bignum)


if pub_key.y % 2 == 0 # y is even
leader = "\x02"
else
leader = "\x03"
end
pub_key_with_lead = leader + [pub_key.x.to_hexa].pack("H*")


pub_key_sha256 = Digest::SHA256.digest(pub_key_with_lead)
pub_key_hash = Digest::RMD160.digest(pub_key_sha256)

pub_key_hash_and_version_and_checksum = cat_checksum("\x00" + pub_key_hash)
pub_addr = pub_key_hash_and_version_and_checksum.to_base58

It generates bitcoin addresses that are not correct so I assume Im making something wrong, also I would like to know what changes I have to make to get the compressed and uncompressed addresses of the private key
achow101
Moderator
Legendary
*
Offline Offline

Activity: 3542
Merit: 6886


Just writing some code


View Profile WWW
December 15, 2016, 08:12:57 PM
 #11

What is that sha1 variable that you are getting the pubkey of? You should be getting the pubkey of the private key, which is 1.

acegilz (OP)
Full Member
***
Offline Offline

Activity: 211
Merit: 100

1ACEGiLZnZoG7KUNkMwAT8tBuJ6jsrwj5Q


View Profile
December 15, 2016, 08:36:44 PM
 #12

What is that sha1 variable that you are getting the pubkey of? You should be getting the pubkey of the private key, which is 1.

Yes, if you check the first code block its the hashing of the hex code of 80.........00001
achow101
Moderator
Legendary
*
Offline Offline

Activity: 3542
Merit: 6886


Just writing some code


View Profile WWW
December 15, 2016, 08:51:56 PM
 #13

What is that sha1 variable that you are getting the pubkey of? You should be getting the pubkey of the private key, which is 1.

Yes, if you check the first code block its the hashing of the hex code of 80.........00001
That hash IS NOT the private key. Your private key is just 1, nothing else. The 80 bye on front is not part of the private key. The hash is not the private key. Your private key is just 1.

DannyHamilton
Legendary
*
Offline Offline

Activity: 3486
Merit: 4851



View Profile
December 15, 2016, 09:00:05 PM
 #14

What is that sha1 variable that you are getting the pubkey of? You should be getting the pubkey of the private key, which is 1.

Yes, if you check the first code block its the hashing of the hex code of 80.........00001

So, then you are NOT calculating the bitcoin address of private key 1

You are calculating the bitcoin address of private key 76148737704215984528336581924048280615126714225363445232814723661301765265283.
(which is that value you get when you double hash 0x800000000000000000000000000000000000000000000000000000000000000001)

The addresses you should get in that case would be:
1BajJZaEgv6AoHrm96Yb83gdPFqC2NhHJg (Compressed Address)
19xWR81nzzn4LRV8dnAzJ46ip6L2Co4Rpa (Uncompressed Address)

If you want the bitcoin address of the private key 1, then you need to calculate
curve.generator.multiply_by_scalar()

on the value 1 (not the hash of 1).
DannyHamilton
Legendary
*
Offline Offline

Activity: 3486
Merit: 4851



View Profile
December 15, 2016, 09:18:26 PM
 #15

It really sounds like you need to work on understanding some of the basics before you start trying to write code.

A bitcoin private key is just a random integer.  Any integer between 1 and 115792089237316195423570985008687907852837564279074904382605163141518161494336 is a valid private key.  Just pick a random integer, and you've got a private key.  In the case of this thread, you've chosen the number 1.

Now, once you have your integer you can represent that integer in any preferred format.

For example, you could represent it as a 256 bit binary number:
0b00000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000001

Or you could represent it as a 64 digit hex number (representing the 32 bytes):
0x0000000000000000000000000000000000000000000000000000000000000001

Or you could represent it in Wallet Import Format (WIF):
5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf

No matter what representation you use, the end result is that the value of the actual private key is 1.

To calculate the public key, you need to multiply the base point "G" on the Secp256k1 curve by the VALUE of the private key (in this case, 1).

Then to get a bitcoin address, you need to SHA256 hash the public key, then RIPEMD160 hash the result of the SHA256 hash, then calculate the base58check representation of the the RIPEMD160 hash.

The hashing that achow101 explained to you at the top of this thread was for the purposes of computing a CHECKSUM.  That's a value that is stored in the WIF that can be used to verify that the user didn't make a typing error while entering their private key.  The 4 bytes from the hash (and first byte version number) need to be removed from the WIF representation before you try to calculate the public key.
acegilz (OP)
Full Member
***
Offline Offline

Activity: 211
Merit: 100

1ACEGiLZnZoG7KUNkMwAT8tBuJ6jsrwj5Q


View Profile
December 16, 2016, 01:23:54 AM
Last edit: December 16, 2016, 01:39:30 AM by acegilz
 #16

Great! Thank you both for the detailed reply. Honestly I have been looking for replies like these everywhere without success, that's why I opened this.
One last question, I could generate a compressed address, what changes or extras do I have to make to get the uncompressed address?

Edit: Gotcha!
    
Code:
uncompressed = "\x04" + [pub_key.x.to_hexa].pack("H*") + [pub_key.y.to_hexa].pack("H*")
acegilz (OP)
Full Member
***
Offline Offline

Activity: 211
Merit: 100

1ACEGiLZnZoG7KUNkMwAT8tBuJ6jsrwj5Q


View Profile
December 16, 2016, 12:35:05 PM
Last edit: December 16, 2016, 12:48:55 PM by acegilz
 #17

Do you understand how could I change the function
Code:
curve.generator.multiply_by_scalar(record)
from the ECDSA gem

by something provided by native openssl?

The first solution takes 30 seconds to load 100 records (300ms each), I heard the openssl is pretty much faster but I don't find anything equivalent there(maybe there isn't..)

If I understand correctly we are expanding the Ecurve n times ( the private key numbers) and then we use some coordinate (x or y dunno) based on the other coordinate (as reference) attributed with the value of n
acegilz (OP)
Full Member
***
Offline Offline

Activity: 211
Merit: 100

1ACEGiLZnZoG7KUNkMwAT8tBuJ6jsrwj5Q


View Profile
December 16, 2016, 01:08:32 PM
 #18

Bounty of BTC0.01 added for who could explain me how to put this working efficiently in ruby.
It's urgent and I can't find it out by myself
Coding Enthusiast
Legendary
*
Offline Offline

Activity: 1043
Merit: 2818


Bitcoin and C♯ Enthusiast


View Profile WWW
December 16, 2016, 03:52:11 PM
 #19

https://www.google.com/search?q=bitcoin+private+key+generate+in+ruby
Here is an open source Ruby Library: https://github.com/lian/bitcoin-ruby
I believe this is the part you need: https://github.com/lian/bitcoin-ruby/blob/master/lib/bitcoin/key.rb

http://www.rubydoc.info/github/lian/bitcoin-ruby/Bitcoin/Key

Donate to the author of the library if you found it helpful.

Also helpful: https://royalforkblog.github.io/2014/07/31/address-gen/

Projects List+Suggestion box
Donate: 1Q9s or bc1q
|
|
|
FinderOuter(0.20.0)Ann-git
Denovo(0.7.0)Ann-git
Bitcoin.Net(0.26.0)Ann-git
|
|
|
BitcoinTransactionTool(0.11.0)Ann-git
WatchOnlyBitcoinWallet(3.2.1)Ann-git
SharpPusher(0.12.0)Ann-git
acegilz (OP)
Full Member
***
Offline Offline

Activity: 211
Merit: 100

1ACEGiLZnZoG7KUNkMwAT8tBuJ6jsrwj5Q


View Profile
December 17, 2016, 07:48:48 PM
 #20

http://stackoverflow.com/questions/22293864/ruby-openssl-convert-elliptic-curve-point-octet-string-into-opensslpkeyec

Code:
key =  '04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284'
key_bn = OpenSSL::BN.new(key, 16) #Input: 16=Hexa, Output: BigNumber
group = OpenSSL::PKey::EC::Group.new('secp256k1')

point = OpenSSL::PKey::EC::Point.new(group, key_bn)

Is it possible to get the x and y coordinates individually from point? I think I can get the merged coordinates with
Code:
point.to_bn.to_s
but that is not enough to generate an address
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!