java 比特币私钥生成_如何生成自己的比特币私钥
java 比特幣私鑰生成
In cryptocurrencies, a private key allows a user to gain access to their wallet. The person who holds the private key fully controls the coins in that wallet. For this reason, you should keep it secret. And if you really want to generate the key yourself, it makes sense to generate it in a secure way.
在加密貨幣中,私鑰允許用戶訪問其錢包。 持有私鑰的人可以完全控制該錢包中的硬幣。 因此,您應(yīng)該對其保密。 而且,如果您真的想自己生成密鑰,則以安全的方式生成密鑰是有意義的。
Here, I will provide an introduction to private keys and show you how you can generate your own key using various cryptographic functions. I will provide a description of the algorithm and the code in Python.
在這里,我將對私鑰進(jìn)行介紹,并向您展示如何使用各種加密功能生成自己的密鑰。 我將提供Python中的算法和代碼的描述。
我需要生成一個私鑰嗎? (Do I need to generate a private key?)
Most of the time you don’t. For example, if you use a web wallet like Coinbase or Blockchain.info, they create and manage the private key for you. It’s the same for exchanges.
大多數(shù)時候你不這樣做。 例如,如果您使用Coinbase或Blockchain.info之類的網(wǎng)絡(luò)錢包,它們將為您創(chuàng)建和管理私鑰。 交流是一樣的。
Mobile and desktop wallets usually also generate a private key for you, although they might have the option to create a wallet from your own private key.
移動和臺式機錢包通常還可以為您生成一個私鑰,盡管它們可以選擇根據(jù)您自己的私鑰創(chuàng)建一個錢包。
So why generate it anyway? Here are the reasons that I have:
那么為什么要生成它呢? 這是我有的原因:
- You want to make sure that no one knows the key 您要確保沒有人知道鑰匙
- You just want to learn more about cryptography and random number generation (RNG) 您只想了解有關(guān)加密和隨機數(shù)生成(RNG)的更多信息
私鑰到底是什么? (What exactly is a private key?)
Formally, a private key for Bitcoin (and many other cryptocurrencies) is a series of 32 bytes. Now, there are many ways to record these bytes. It can be a string of 256 ones and zeros (32 * 8 = 256) or 100 dice rolls. It can be a binary string, Base64 string, a WIF key, mnemonic phrase, or finally, a hex string. For our purposes, we will use a 64 character long hex string.
正式而言,比特幣(和許多其他加密貨幣)的私鑰是一系列的32個字節(jié)。 現(xiàn)在,有很多方法可以記錄這些字節(jié)。 它可以是256個1和0(32 * 8 = 256)或100個骰子骰的字符串。 它可以是二進(jìn)制字符串,Base64字符串, WIF鍵 , 助記詞或最后一個十六進(jìn)制字符串。 為了我們的目的,我們將使用64個字符的十六進(jìn)制字符串。
Why exactly 32 bytes? Great question! You see, to create a public key from a private one, Bitcoin uses the ECDSA, or Elliptic Curve Digital Signature Algorithm. More specifically, it uses one particular curve called secp256k1.
為什么是32個字節(jié)? 好問題! 您會看到,為了從私鑰創(chuàng)建公鑰,比特幣使用ECDSA或橢圓曲線數(shù)字簽名算法。 更具體地說,它使用一條稱為secp256k1的特定曲線。
Now, this curve has an order of 256 bits, takes 256 bits as input, and outputs 256-bit integers. And 256 bits is exactly 32 bytes. So, to put it another way, we need 32 bytes of data to feed to this curve algorithm.
現(xiàn)在,該曲線的階數(shù)為256位,以256位為輸入,并輸出256位整數(shù)。 256位恰好是32個字節(jié)。 因此,換句話說,我們需要32字節(jié)的數(shù)據(jù)才能饋入此曲線算法。
There is an additional requirement for the private key. Because we use ECDSA, the key should be positive and should be less than the order of the curve. The order of secp256k1 is FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141, which is pretty big: almost any 32-byte number will be smaller than it.
私鑰還有其他要求。 由于我們使用ECDSA,因此關(guān)鍵點應(yīng)為正,并且應(yīng)小于曲線的階數(shù)。 secp256k1的順序為FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 ,它的大小非常大:幾乎所有32字節(jié)的數(shù)字都小于它。
天真的方法 (Naive method)
So, how do we generate a 32-byte integer? The first thing that comes to mind is to just use an RNG library in your language of choice. Python even provides a cute way of generating just enough bits:
那么,我們?nèi)绾紊梢粋€32字節(jié)的整數(shù)? 首先想到的是只使用您選擇的語言使用RNG庫。 Python甚至提供了一種可愛的方式來生成足夠的位:
import random bits = random.getrandbits(256) # 30848827712021293731208415302456569301499384654877289245795786476741155372082 bits_hex = hex(bits) # 0x4433d156e8c53bf5b50af07aa95a29436f29a94e0ccc5d58df8e57bdc8583c32 private_key = bits_hex[2:] # 4433d156e8c53bf5b50af07aa95a29436f29a94e0ccc5d58df8e57bdc8583c32Looks good, but actually, it’s not. You see, normal RNG libraries are not intended for cryptography, as they are not very secure. They generate numbers based on a seed, and by default, the seed is the current time. That way, if you know approximately when I generated the bits above, all you need to do is brute-force a few variants.
看起來不錯,但實際上并非如此。 您會看到,普通的RNG庫不是用于加密,因為它們不是很安全。 它們根據(jù)種子生成數(shù)字,默認(rèn)情況下,種子是當(dāng)前時間。 這樣,如果您大概知道我何時生成了上面的位,那么您所要做的就是蠻力地制造一些變體。
When you generate a private key, you want to be extremely secure. Remember, if anyone learns the private key, they can easily steal all the coins from the corresponding wallet, and you have no chance of ever getting them back.
當(dāng)您生成私鑰時,您希望非常安全。 請記住,如果有人學(xué)習(xí)了私鑰,他們可以輕松地從相應(yīng)的錢包中竊取所有硬幣,并且您將永遠(yuǎn)沒有機會將它們?nèi)』亍?
So let’s try to do it more securely.
因此,讓我們嘗試更安全地進(jìn)行操作。
具有加密功能的RNG (Cryptographically strong RNG)
Along with a standard RNG method, programming languages usually provide a RNG specifically designed for cryptographic operations. This method is usually much more secure, because it draws entropy straight from the operating system. The result of such RNG is much harder to reproduce. You can’t do it by knowing the time of generation or having the seed, because there is no seed. Well, at least the user doesn’t enter a seed — rather, it’s created by the program.
與標(biāo)準(zhǔn)RNG方法一起,編程語言通常會提供專門為密碼操作設(shè)計的RNG。 這種方法通常更安全,因為它直接從操作系統(tǒng)中獲取熵。 這種RNG的結(jié)果很難復(fù)制。 您無法通過知道生成時間或擁有種子來做到這一點,因為沒有種子。 好吧,至少用戶沒有輸入種子,而是由程序創(chuàng)建的。
In Python, cryptographically strong RNG is implemented in the secrets module. Let’s modify the code above to make the private key generation secure!
在Python中, secrets模塊中實現(xiàn)了具有加密功能的RNG。 讓我們修改上面的代碼以確保私鑰生成的安全!
import secrets bits = secrets.randbits(256) # 46518555179467323509970270980993648640987722172281263586388328188640792550961 bits_hex = hex(bits) # 0x66d891b5ed7f51e5044be6a7ebe4e2eae32b960f5aa0883f7cc0ce4fd6921e31 private_key = bits_hex[2:] # 66d891b5ed7f51e5044be6a7ebe4e2eae32b960f5aa0883f7cc0ce4fd6921e31That is amazing. I bet you wouldn’t be able to reproduce this, even with access to my PC. But can we go deeper?
這是驚人的。 我敢打賭,即使使用我的電腦,您也將無法重現(xiàn)此內(nèi)容。 但是我們可以更深入嗎?
專業(yè)網(wǎng)站 (Specialized sites)
There are sites that generate random numbers for you. We will consider just two here. One is random.org, a well-known general purpose random number generator. Another one is bitaddress.org, which is designed specifically for Bitcoin private key generation.
有些網(wǎng)站會為您生成隨機數(shù)。 我們這里只考慮兩個。 一個是random.org ,這是眾所周知的通用隨機數(shù)生成器。 另一個是bitaddress.org ,它是專門為生成比特幣私鑰而設(shè)計的。
Can random.org help us generate a key? Definitely, as they have service for generating random bytes. But two problems arise here. Random.org claims to be a truly random generator, but can you trust it? Can you be sure that it is indeed random? Can you be sure that the owner doesn’t record all generation results, especially ones that look like private keys? The answer is up to you. Oh, and you can’t run it locally, which is an additional problem. This method is not 100% secure.
random.org可以幫助我們生成密鑰嗎? 當(dāng)然,因為他們的服務(wù)生成隨機字節(jié)。 但是這里出現(xiàn)兩個問題。 Random.org聲稱是真正的隨機生成器,但是您可以信任它嗎? 您可以確定它確實是隨機的嗎? 您可以確定所有者不會記錄所有生成結(jié)果,尤其是看起來像私鑰的結(jié)果嗎? 答案取決于您。 哦,您不能在本地運行它,這是另一個問題。 此方法不是100%安全的。
Now, bitaddress.org is a whole different story. It’s open source, so you can see what’s under its hood. It’s client-side, so you can download it and run it locally, even without an Internet connection.
現(xiàn)在, bitaddress.org是一個完全不同的故事。 它是開源的,因此您可以看到它的內(nèi)幕。 它是客戶端,因此即使沒有Internet連接,也可以下載并在本地運行。
So how does it work? It uses you — yes, you — as a source of entropy. It asks you to move your mouse or press random keys. You do it long enough to make it infeasible to reproduce the results.
那么它是怎樣工作的? 它使用您(是的,您)作為熵的來源。 它要求您移動鼠標(biāo)或按隨機鍵。 您所做的時間足夠長,以致無法再現(xiàn)結(jié)果。
Are you interested to see how bitaddress.org works? For educational purposes, we will look at its code and try to reproduce it in Python.
您是否有興趣查看bitaddress.org的工作原理? 出于教育目的,我們將查看其代碼并嘗試在Python中重現(xiàn)它。
Quick note: bitaddress.org gives you the private key in a compressed WIF format, which is close to the WIF format that we discussed before. For our purposes, we will make the algorithm return a hex string so that we can use it later for a public key generation.
快速說明:bitaddress.org為您提供壓縮WIF格式的私鑰,該私鑰與我們之前討論的WIF格式相似。 出于我們的目的,我們將使算法返回一個十六進(jìn)制字符串,以便以后可以將其用于生成公共密鑰。
位地址:詳細(xì)信息 (Bitaddress: the specifics)
Bitaddress creates the entropy in two forms: by mouse movement and by key pressure. We’ll talk about both, but we’ll focus on the key presses, as it’s hard to implement mouse tracking in the Python lib. We’ll expect the end user to type buttons until we have enough entropy, and then we’ll generate a key.
位地址以兩種形式創(chuàng)建熵:通過鼠標(biāo)移動和通過按鍵。 我們將討論兩者,但我們將重點放在按鍵上,因為很難在Python庫中實現(xiàn)鼠標(biāo)跟蹤。 我們希望最終用戶鍵入按鈕,直到我們有足夠的熵,然后再生成一個鍵。
Bitaddress does three things. It initializes byte array, trying to get as much entropy as possible from your computer, it fills the array with the user input, and then it generates a private key.
位地址可做三件事。 它初始化字節(jié)數(shù)組,嘗試從您的計算機中獲取盡可能多的熵,并用用戶輸入填充該數(shù)組,然后生成一個私鑰。
Bitaddress uses the 256-byte array to store entropy. This array is rewritten in cycles, so when the array is filled for the first time, the pointer goes to zero, and the process of filling starts again.
位地址使用256字節(jié)數(shù)組存儲熵。 該數(shù)組將以周期重寫,因此,第一次填充該數(shù)組時,指針將變?yōu)榱?#xff0c;并且填充過程將再次開始。
The program initiates an array with 256 bytes from window.crypto. Then, it writes a timestamp to get an additional 4 bytes of entropy. Finally, it gets such data as the size of the screen, your time zone, information about browser plugins, your locale, and more. That gives it another 6 bytes.
該程序從window.crypto啟動一個具有256個字節(jié)的數(shù)組。 然后,它編寫一個時間戳以獲取額外的4個字節(jié)的熵。 最后,它獲得諸如屏幕大小,您的時區(qū),有關(guān)瀏覽器插件的信息,您的語言環(huán)境等信息。 這又給了它6個字節(jié)。
After the initialization, the program continually waits for user input to rewrite initial bytes. When the user moves the cursor, the program writes the position of the cursor. When the user presses buttons, the program writes the char code of the button pressed.
初始化之后,程序?qū)⒗^續(xù)等待用戶輸入以重寫初始字節(jié)。 當(dāng)用戶移動光標(biāo)時,程序?qū)懭牍鈽?biāo)的位置。 當(dāng)用戶按下按鈕時,程序?qū)懭胨聪掳粹o的字符代碼。
Finally, bitaddress uses accumulated entropy to generate a private key. It needs to generate 32 bytes. For this task, bitaddress uses an RNG algorithm called ARC4. The program initializes ARC4 with the current time and collected entropy, then gets bytes one by one 32 times.
最后,位地址使用累積的熵來生成私鑰。 它需要生成32個字節(jié)。 對于此任務(wù),位地址使用稱為ARC4的RNG算法。 該程序?qū)⑹褂卯?dāng)前時間初始化ARC4并收集熵,然后將字節(jié)1乘以32。
This is all an oversimplification of how the program works, but I hope that you get the idea. You can check out the algorithm in full detail on Github.
這一切都過于簡化了程序的工作方式,但是我希望您能理解。 您可以在Github上詳細(xì)了解算法。
自己動手 (Doing it yourself)
For our purposes, we’ll build a simpler version of bitaddress. First, we won’t collect data about the user’s machine and location. Second, we will input entropy only via text, as it’s quite challenging to continually receive mouse position with a Python script (check PyAutoGUI if you want to do that).
為了我們的目的,我們將構(gòu)建一個更簡單的bitaddress版本。 首先,我們不會收集有關(guān)用戶機器和位置的數(shù)據(jù)。 其次,我們將僅通過文本輸入熵,因為使用Python腳本連續(xù)接收鼠標(biāo)位置非常困難(如果要這樣做,請檢查PyAutoGUI )。
That brings us to the formal specification of our generator library. First, it will initialize a byte array with cryptographic RNG, then it will fill the timestamp, and finally it will fill the user-created string. After the seed pool is filled, the library will let the developer create a key. Actually, they will be able to create as many private keys as they want, all secured by the collected entropy.
這使我們成為生成器庫的正式規(guī)范。 首先,它將使用加密的RNG初始化字節(jié)數(shù)組,然后將填充時間戳,最后將填充用戶創(chuàng)建的字符串。 種子池填滿后,庫將允許開發(fā)人員創(chuàng)建密鑰。 實際上,他們將能夠根據(jù)需要創(chuàng)建任意數(shù)量的私鑰,全部由收集的熵保護(hù)。
初始化池 (Initializing the pool)
Here we put some bytes from cryptographic RNG and a timestamp. __seed_int and __seed_byte are two helper methods that insert the entropy into our pool array. Notice that we use secrets.
在這里,我們從加密RNG和時間戳中放入了一些字節(jié)。 __seed_int和__seed_byte是兩個將熵插入到我們的池數(shù)組中的輔助方法。 注意,我們使用secrets 。
def __init_pool(self):for i in range(self.POOL_SIZE):random_byte = secrets.randbits(8)self.__seed_byte(random_byte)time_int = int(time.time())self.__seed_int(time_int) def __seed_int(self, n):self.__seed_byte(n)self.__seed_byte(n >> 8)self.__seed_byte(n >> 16)self.__seed_byte(n >> 24) def __seed_byte(self, n):self.pool[self.pool_pointer] ^= n & 255self.pool_pointer += 1if self.pool_pointer >= self.POOL_SIZE:self.pool_pointer = 0輸入播種 (Seeding with input)
Here we first put a timestamp and then the input string, character by character.
在這里,我們首先放置一個時間戳,然后逐個字符地輸入字符串。
def seed_input(self, str_input):time_int = int(time.time())self.__seed_int(time_int)for char in str_input:char_code = ord(char)self.__seed_byte(char_code)生成私鑰 (Generating the private key)
This part might look hard, but it’s actually very simple.
這部分可能很難看,但實際上非常簡單。
First, we need to generate 32-byte number using our pool. Unfortunately, we can’t just create our own random object and use it only for the key generation. Instead, there is a shared object that is used by any code that is running in one script.
首先,我們需要使用我們的池生成32字節(jié)的數(shù)字。 不幸的是,我們不能僅僅創(chuàng)建自己的random對象并將其僅用于密鑰生成。 而是有一個共享對象,供一個腳本中運行的任何代碼使用。
What does that mean for us? It means that at each moment, anywhere in the code, one simple random.seed(0) can destroy all our collected entropy. We don’t want that. Thankfully, Python provides getstate and setstate methods. So, to save our entropy each time we generate a key, we remember the state we stopped at and set it next time we want to make a key.
這對我們意味著什么? 這意味著在代碼的任何地方,每個時刻,一個簡單的random.seed(0)都會破壞我們收集的所有熵。 我們不想要那個。 幸運的是,Python提供了getstate和setstate方法。 因此,為了在每次生成密鑰時保存熵,我們會記住停下來的狀態(tài),并在下次要創(chuàng)建密鑰時進(jìn)行設(shè)置。
Second, we just make sure that our key is in range (1, CURVE_ORDER). This is a requirement for all ECDSA private keys. The CURVE_ORDER is the order of the secp256k1 curve, which is FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141.
其次,我們只需確保我們的密鑰在范圍內(nèi)(1, CURVE_ORDER )。 這是所有ECDSA私鑰的要求。 CURVE_ORDER是secp256k1曲線的順序,即FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 。
Finally, for convenience, we convert to hex, and strip the ‘0x’ part.
最后,為方便起見,我們將其轉(zhuǎn)換為十六進(jìn)制,并去除“ 0x”部分。
def generate_key(self):big_int = self.__generate_big_int()big_int = big_int % (self.CURVE_ORDER — 1) # key < curve orderbig_int = big_int + 1 # key > 0key = hex(big_int)[2:]return key def __generate_big_int(self):if self.prng_state is None:seed = int.from_bytes(self.pool, byteorder=’big’, signed=False)random.seed(seed)self.prng_state = random.getstate()random.setstate(self.prng_state)big_int = random.getrandbits(self.KEY_BYTES * 8)self.prng_state = random.getstate()return big_int在行動 (In action)
Let’s try to use the library. Actually, it’s really simple: you can generate a private key in three lines of code!
讓我們嘗試使用該庫。 實際上,這非常簡單:您可以用三行代碼生成一個私鑰!
kg = KeyGenerator() kg.seed_input(‘Truly random string. I rolled a dice and got 4.’) kg.generate_key() # 60cf347dbc59d31c1358c8e5cf5e45b822ab85b79cb32a9f3d98184779a9efc2You can see it yourself. The key is random and totally valid. Moreover, each time you run this code, you get different results.
您可以自己查看。 密鑰是隨機的,并且完全有效。 而且,每次運行此代碼,您都會得到不同的結(jié)果。
結(jié)論 (Conclusion)
As you can see, there are a lot of ways to generate private keys. They differ in simplicity and security.
如您所見,有很多生成私鑰的方法。 它們在簡單性和安全性方面有所不同。
Generating a private key is only a first step. The next step is extracting a public key and a wallet address that you can use to receive payments. The process of generating a wallet differs for Bitcoin and Ethereum, and I plan to write two more articles on that topic.
生成私鑰只是第一步。 下一步是提取可用于接收付款的公鑰和錢包地址。 比特幣和以太坊生成錢包的過程有所不同,我計劃就該主題再寫兩篇文章。
If you want to play with the code, I published it to this Github repository.
如果您想使用這些代碼,我將其發(fā)布到了這個Github倉庫 。
I am making a course on cryptocurrencies here on freeCodeCamp News. The first part is a detailed description of the blockchain.
我正在freeCodeCamp News上開設(shè)有關(guān)加密貨幣的課程。 第一部分是對區(qū)塊鏈的詳細(xì)描述。
I also post random thoughts about crypto on Twitter, so you might want to check it out.
我還在Twitter上發(fā)布了關(guān)于加密的隨機想法,因此您可能需要檢查一下。
翻譯自: https://www.freecodecamp.org/news/how-to-generate-your-very-own-bitcoin-private-key-7ad0f4936e6c/
java 比特幣私鑰生成
總結(jié)
以上是生活随笔為你收集整理的java 比特币私钥生成_如何生成自己的比特币私钥的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 周公解梦梦到玉米棒子是什么意思
- 下一篇: 如何使用Webpack 4简化React