讓咱們經過學習比特幣(Bitcoin)如何實施該技術的各個方面來工做,好嗎?該技術包括如下幾個方面:php
警告的提示——這裏的代碼僅用於學習。若是你試圖將比特幣發送到由該代碼生成的地址,你可能會損失金錢。java
比特幣地址是一個隨機查找的十六進制字符串,在比特幣網絡中用於發送和接收比特幣。它是公私不對稱ECDSA
密鑰的公共部分。相應的私鑰用於簽署比特幣交易,做爲交易時來自你的確認和證實。node
從技術上講,比特幣地址是從ECDSA
密鑰的公共部分生成的,使用SHA-256
和RIPEMD-160
進行hash,以下文所述,處理獲得的結果hash,最後使用Base58
校驗編碼對密鑰進行編碼。python
讓咱們看看如何使用JCE(java加密擴展),Bouncy Castle(RIPEMD-160)以及最後在bitcoinj庫中使用Base58編碼功能來完成全部這些工做。android
咱們以前已經介紹過生成RSA公鑰和私鑰。比特幣使用ECDSA
代替RSA
做爲關鍵算法。它生成以下:git
爲Elliptic Curve
算法建立KeyPairGenerator
。程序員
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
使用指定橢圓曲線是secp256k1。github
ECGenParameterSpec ecSpec = new ECGenParameterSpec("secp256k1"); keyGen.initialize(ecSpec);
一旦得到KeyPairGenerator
後,你能夠建立KeyPair
即密鑰對,從中能夠獲取公鑰和私鑰。web
KeyPair kp = keyGen.generateKeyPair(); PublicKey pub = kp.getPublic(); PrivateKey pvt = kp.getPrivate();
你能夠只存儲密鑰的私有部分,由於公鑰能夠從私鑰派生。算法
ECPrivateKey epvt = (ECPrivateKey)pvt; String sepvt = adjustTo64(epvt.getS().toString(16)).toUpperCase(); System.out.println("s[" + sepvt.length() + "]: " + sepvt);
靜態方法adjustTo64()
僅填充帶有前導0的十六進制字符串,所以總長度爲64個字符。
static private String adjustTo64(String s) { switch(s.length()) { case 62: return "00" + s; case 63: return "0" + s; case 64: return s; default: throw new IllegalArgumentException("not a valid key: " + s); } }
這是由上面的代碼生成的示例私鑰。
s[64]: 024C8E05018319CED4BB04E184C307BFF115976A05F974C7D945B5151E490ADE
這個值一般是由數字錢包存儲的值。
上面生成的密鑰的公共部分被編碼爲比特幣地址。首先,ECDSA密鑰由橢圓曲線上的點表示。該點的X和Y座標包括公鑰。它們在開頭與「04」鏈接在一塊兒表明公鑰。
ECPublicKey epub = (ECPublicKey)pub; ECPoint pt = epub.getW(); String sx = adjustTo64(pt.getAffineX().toString(16)).toUpperCase(); String sy = adjustTo64(pt.getAffineY().toString(16)).toUpperCase(); String bcPub = "04" + sx + sy; System.out.println("bcPub: " + bcPub); # prints bcPub: 04CAAA5C0BDDAA22C9D3C0DDAEC8550791891BB2C2FB0F9084D02F927537DE4F443ACED7DEB488E9BFE60D6C68596E6C78D95E20622CC05474FD962392BDC6AF29
咱們如今須要在公鑰上執行SHA-256
,而後是RIPEMD-160
。
MessageDigest sha = MessageDigest.getInstance("SHA-256"); byte[] s1 = sha.digest(bcPub.getBytes("UTF-8")); System.out.println(" sha: " + bytesToHex(s1).toUpperCase()); # prints sha: 7524DC35AEB4B62A0F1C90425ADC6732A7C5DF51A72E8B90983629A7AEC656A0
咱們使用Bouncy Castle
提供程序來執行RIPEMD-160
,由於JCE
沒有實現此算法。
MessageDigest rmd = MessageDigest.getInstance("RipeMD160", "BC"); byte[] r1 = rmd.digest(s1);
接下來,咱們須要在哈希開頭添加一個0x00的版本字節。
byte[] r2 = new byte[r1.length + 1]; r2[0] = 0; for (int i = 0 ; i < r1.length ; i++) r2[i+1] = r1[i]; System.out.println(" rmd: " + bytesToHex(r2).toUpperCase()); # prints rmd: 00C5FAE41AB21FA56CFBAFA3AE7FB5784441D11CEC
咱們如今須要對上面的結果執行兩次SHA-256哈希。
byte[] s2 = sha.digest(r2); System.out.println(" sha: " + bytesToHex(s2).toUpperCase()); byte[] s3 = sha.digest(s2); System.out.println(" sha: " + bytesToHex(s3).toUpperCase());
第二次散列結果的前4個字節用做地址校驗和。它附加到上面的RIPEMD160
哈希。這是25字節的比特幣地址。
byte[] a1 = new byte[25]; for (int i = 0 ; i < r2.length ; i++) a1[i] = r2[i]; for (int i = 0 ; i < 5 ; i++) a1[20 + i] = s3[i];
咱們如今使用bitcoinj
庫中的Base58.encode()
方法來得到最終的比特幣地址。
System.out.println(" adr: " + Base58.encode(a1)); # prints adr: 1K3pg1JFPtW7NvKNA77YCVghZRq2s1LwVF
這是比特幣應在交易中發送到的地址。
這是一個如何在java中生成比特幣地址的演示文稿。咱們生成一個ECDSA
密鑰對,使用SHA256
和RIPEMD160
哈希密鑰的公共部分。最後,咱們經過執行SHA256
兩次並選取前4個字節來計算校驗和,該字節附加到上面的RIPEMD160
哈希。結果使用Base58
編碼進行編碼。
以爲有點複雜,也能夠看這個Java離線生成比特幣地址
建議你瀏覽咱們匯智網的各類編程語言的區塊鏈教程和區塊鏈技術博客,更深刻了解區塊鏈,比特幣,加密貨幣,以太坊,和智能合約。
- java比特幣開發教程,本課程面向初學者,內容即涵蓋比特幣的核心概念,例如區塊鏈存儲、去中心化共識機制、密鑰與腳本、交易與UTXO等,同時也詳細講解如何在Java代碼中集成比特幣支持功能,例如建立地址、管理錢包、構造裸交易等,是Java工程師不可多得的比特幣開發學習課程。
- php比特幣開發教程,本課程面向初學者,內容即涵蓋比特幣的核心概念,例如區塊鏈存儲、去中心化共識機制、密鑰與腳本、交易與UTXO等,同時也詳細講解如何在Php代碼中集成比特幣支持功能,例如建立地址、管理錢包、構造裸交易等,是Php工程師不可多得的比特幣開發學習課程。
- php以太坊,主要是介紹使用php進行智能合約開發交互,進行帳號建立、交易、轉帳、代幣開發以及過濾器和交易等內容。
- java以太坊開發教程,主要是針對java和android程序員進行區塊鏈以太坊開發的web3j詳解。
- 以太坊入門教程,主要介紹智能合約與dapp應用開發,適合入門。
- 以太坊開發進階教程,主要是介紹使用node.js、mongodb、區塊鏈、ipfs實現去中心化電商DApp實戰,適合進階。
- python以太坊,主要是針對python工程師使用web3.py進行區塊鏈以太坊開發的詳解。
- C#以太坊,主要講解如何使用C#開發基於.Net的以太坊應用,包括帳戶管理、狀態與交易、智能合約開發與交互、過濾器和交易等。
- EOS入門教程,本課程幫助你快速入門EOS區塊鏈去中心化應用的開發,內容涵蓋EOS工具鏈、帳戶與錢包、發行代幣、智能合約開發與部署、使用代碼與智能合約交互等核心知識點,最後綜合運用各知識點完成一個便籤DApp的開發。
匯智網原創翻譯,轉載請標明出處。這裏是原文