1. 程式人生 > >pybitcointools原始碼分析之由私鑰獲取公鑰

pybitcointools原始碼分析之由私鑰獲取公鑰

私鑰其實就是一串隨機的數字而已。有了私鑰,我們可以使用橢圓曲線乘法產生一個公鑰。本篇使用的私鑰示例是:

e9873d79c6d87dc0fb6a5778633389f4453213303da61f20bd67fc233aa33262

這其實是一個32位元組的16進製表示的數字,這裡是為了方便寫成字串的形式。

使用的函式是,

#由私鑰獲取公鑰
def privkey_to_pubkey(privkey):
    f = get_privkey_format(privkey)

    privkey = decode_privkey(privkey, f)
    if privkey >= N:
        raise
Exception("Invalid privkey") if f in ['bin', 'bin_compressed', 'hex', 'hex_compressed', 'decimal']: return encode_pubkey(fast_multiply(G, privkey), f) else: return encode_pubkey(fast_multiply(G, privkey), f.replace('wif', 'hex'))

get_privkey_format函式用於判斷私鑰的格式,為下面的處理鋪墊。

def
get_privkey_format(priv):
if isinstance(priv, int_types): return 'decimal' elif len(priv) == 32: return 'bin' elif len(priv) == 33: return 'bin_compressed' elif len(priv) == 64: return 'hex' elif len(priv) == 66: return 'hex_compressed' else: bin_p = b58check_to_bin(priv) if
len(bin_p) == 32: return 'wif' elif len(bin_p) == 33: return 'wif_compressed' else: raise Exception("WIF does not represent privkey")

我們這裡的示例get_privkey_format返回的是字串”hex”。那其他的格式是什麼意思呢?

比如什麼時候返回”bin”呢?上面的私鑰我們也可以寫成bytes的形式:

b"\xe9\x87=y\xc6\xd8}\xc0\xfbjWxc3\x89\xf4E2\x130=\xa6\x1f \xbdg\xfc#:\xa32b"

這是私鑰的byte表示方法(或者叫二進位制表示法),它的長度是字串的一半,我們可以做個測試:

str1 = "e9873d79c6d87dc0fb6a5778633389f4453213303da61f20bd67fc233aa33262"
str2 = b"\xe9\x87=y\xc6\xd8}\xc0\xfbjWxc3\x89\xf4E2\x130=\xa6\x1f \xbdg\xfc#:\xa32b";

print len(str1);
print len(str2);

輸出:

64
32
#對私鑰解碼
def decode_privkey(priv,formt=None):
    if not formt: formt = get_privkey_format(priv)
    if formt == 'decimal': return priv
    elif formt == 'bin': return decode(priv, 256)
    elif formt == 'bin_compressed': return decode(priv[:32], 256)
    elif formt == 'hex': return decode(priv, 16)
    elif formt == 'hex_compressed': return decode(priv[:64], 16)
    elif formt == 'wif': return decode(b58check_to_bin(priv),256)
    elif formt == 'wif_compressed':
        return decode(b58check_to_bin(priv)[:32],256)
    else: raise Exception("WIF does not represent privkey")

decode_privkey對私鑰進行解碼,返回的是私鑰對應的整型數值。我轉成字串列印的效果是:

105627842363267744400190144423808258002852957479547731009248450467191077417570

這個結果就是上面16進位制私鑰對應的10進位制值。因為這裡都是大數可能不好理解,我舉個例子:

比如str1 = “1a”, 呼叫
decode_privkey(str1, “hex”)
結果是整型數值26。也就是16進位制的1a對應的10進位制是26。

之所以要轉換成10進位制是為了方便後面進行橢圓曲線乘法運算。

if privkey >= N:
    raise Exception("Invalid privkey")

要理解這一條語句就必須弄明白橢圓曲線中N的概念。我幾年前寫過一篇文章:

裡面講到過橢圓曲線演算法,並說明了什麼是N。簡單講要唯一標識一個橢圓曲線需要6個參量,N是其中一個。N是Group的階,Group是ECC中的曲線組,它是ECC演算法的核心,為什麼這麼說呢? 因為這個group裡的所有欄位就確定了曲線的所有資訊, 後面會看到,這裡只是用EC_GROUP_new生成一個空的group, 然後由p,a,b等引數來填充group, 再以這個group為基礎去生成曲線上的點。

私鑰可以是1 和N-1 之間的任何數字

最後一部分,

if f in ['bin', 'bin_compressed', 'hex', 'hex_compressed', 'decimal']:
    return encode_pubkey(fast_multiply(G, privkey), f)

主要是兩個函式,encode_pubkey和fast_multiply。前者比較簡單,先講它。

首先f還是”hex”,fast_multiply的返回結果是一個座標值(X,Y),在python中用元組(tuple)標識。元組裡的兩個元素都是大整數,分別代表X座標和Y座標。

比如這個示例中,結果是,

(40052878126280527701260741223305245603564636128202744842713277751919610658249L, 112427920116541844817408230468149218341228927370925731589596315545721129686052L)

encode_pubkey函式把這個元組中的座標值轉化為對應的16進位制字串形式然後拼接兩個值,最後在前面加上”04”。最終的這個結果就是公鑰的字串表示形式。如下:

04588d202afcc1ee4ab5254c7847ec25b9a135bbda0f2bc69ee1a714749fd77dc9f88ff2a00d7e752d44cbe16e1ebcf0890b76ec7c78886109dee76ccfc8445424

公鑰是在橢圓曲線上的一個點,由一對座標(x,y)組成。公鑰通常表示為字首04 緊接著兩個256 位元的數字。其中一個256 位元數字是公鑰的x 座標,另一個256 位元數字是y 座標。字首04 是用來區分非壓縮格式公鑰。

fast_multiply是核心,因為由私鑰生成公鑰就是基於橢圓曲線上的一個乘法操作。fast_multiply兩個引數,第一個引數G是個常量,也是前面提到的6個參量之一,privkey是私鑰。對這兩個引數進行乘法的結果就是公鑰。

當然這個乘法並不是我們通常理解的乘法,而是基於橢圓曲線點座標重定義的。關於這部分的具體定義感興趣的可以自己查閱相關資料(反正我查了,相當晦澀難懂)。

相關推薦

pybitcointools原始碼分析獲取

私鑰其實就是一串隨機的數字而已。有了私鑰,我們可以使用橢圓曲線乘法產生一個公鑰。本篇使用的私鑰示例是: e9873d79c6d87dc0fb6a5778633389f4453213303da61f20bd67fc233aa33262 這其實是一個32位元

原始碼閱讀系列】JDK 8 ConcurrentHashMap 原始碼分析 transfer引發的bug

不閱讀原始碼就不會發現這個事兒 前段時間在閱讀ConcurrentHashMap原始碼,版本JDK 8,目前原始碼研究已經告一段落。感謝魯道的ConcurrentHashMap原始碼分析文章,讀到文章,感覺和作者發生了一些交流,解答了很多疑惑,也驗證了一些想法。魯道在簡書的addCount分析文章點這裡&n

Android原始碼分析為什麼在onCreate() 和 onResume() 獲取不到 View 的寬高

轉載自:https://www.jianshu.com/p/d7ab114ac1f7 先來看一段很熟悉的程式碼,可能在最開始接觸安卓的時候,大部分人都寫過的一段程式碼;即嘗試在 onCreate() 和 onResume() 方法中去獲取某個 View 的寬高資訊: 但是列印輸出後,我們會發

Eureka原始碼分析Eureka Client獲取例項資訊流程

下方是Eureka Client從Eureka Server獲取例項資訊的總體流程圖,後面會詳細介紹每個步驟。 Eureka Client在剛啟動的時候會從Eureka Server全量獲取一次註冊資訊,同時初始化Eureka Client本地例項資訊快取定時更新任務,預設30s一次

比特幣原始碼解讀和地址

(本文使用的是比特幣v0.1.0版本 點選下載原始碼)比特幣是建立在數字加密基礎上的,接觸過比特幣的朋友應該知道:(1)購買比特幣最後是通過一個比特幣地址進行的,比特幣地址就像支票中的支付物件(收款方);(2)而比特幣地址則是通過公鑰單向雜湊生成的;(3)而公鑰則是通過私鑰使

asihttp 原始碼分析 獲取請求進度

進度條相關的操作都定義在 ASIProgressDelegate .h 檔案中。 而且所有的方法都是optional的。 ipone上更新進度條的方法 :- (void)setProgress:(float)newProgress; #if TARGET_OS_IPHON

Spark原始碼分析Spark Shell(上)

https://www.cnblogs.com/xing901022/p/6412619.html 文中分析的spark版本為apache的spark-2.1.0-bin-hadoop2.7。 bin目錄結構: -rwxr-xr-x. 1 bigdata bigdata 1089 Dec

Netty 原始碼分析拆包器的奧祕

為什麼要粘包拆包 為什麼要粘包 首先你得了解一下TCP/IP協議,在使用者資料量非常小的情況下,極端情況下,一個位元組,該TCP資料包的有效載荷非常低,傳遞100位元組的資料,需要100次TCP傳送,100次ACK,在應用及時性要求不高的情況下,將這100個有效資料拼接成一個數據包,那會縮短到一個TCP資

netty原始碼分析服務端啟動

ServerBootstrap與Bootstrap分別是netty中服務端與客戶端的引導類,主要負責服務端與客戶端初始化、配置及啟動引導等工作,接下來我們就通過netty原始碼中的示例對ServerBootstrap與Bootstrap的原始碼進行一個簡單的分析。首先我們知道這兩個類都繼承自AbstractB

SNMP原始碼分析(一)配置檔案部分

snmpd.conf想必不陌生。在程序啟動過程中會去讀取配置檔案中各個配置。其中幾個引數需要先知道是幹什麼的:   token:配置檔案的每行的開頭,例如 group MyROGroup v1 readSec 這行token的引數是group。  

【kubernetes/k8s原始碼分析】kubelet原始碼分析cdvisor原始碼分析

  資料流 UnsecuredDependencies -> run   1. cadvisor.New初始化 if kubeDeps.CAdvisorInterface == nil { imageFsInfoProvider := cadv

【kubernetes/k8s原始碼分析】kubelet原始碼分析容器網路初始化原始碼分析

一. 網路基礎   1.1 網路名稱空間的操作 建立網路名稱空間: ip netns add 名稱空間內執行命令: ip netns exec 進入名稱空間: ip netns exec bash   1.2 bridge-nf-c

【kubernetes/k8s原始碼分析】kubelet原始碼分析資源上報

0. 資料流   路徑: pkg/kubelet/kubelet.go   Run函式() ->   syncNodeStatus ()  ->   registerWithAPIServer() ->

【kubernetes/k8s原始碼分析】kubelet原始碼分析啟動容器

主要是呼叫runtime,這裡預設為docker 0. 資料流 NewMainKubelet(cmd/kubelet/app/server.go) -> NewKubeGenericRuntimeManager(pkg/kubelet/kuberuntime/kuberuntime

Android系統原始碼分析-ContentProvider

距離上一次寫部落格已經半年多了,這半年發生了很多事情,也有了很多感觸,最主要是改變了忙碌了工作,更加重視身體的健康,為此也把工作地點從深圳這個一線城市換到了珠海,工作相對沒有那麼累,身體感覺也好了很多。所以在工作完成之餘,也有了更多的時間來自我學習和提高,後續會用更多時間來寫更多實用的東西,幫助我們理解

Vue 原始碼分析proxy代理

Vue 原始碼分析之proxy代理 當我們在使用Vue進行資料設定時,通常初始化格式為: let data = { age: 12, name: 'yang' } // 例項化Vue物件 let vm = new Vue({ data })

Qt原始碼分析事件分發器QEventDispatcherWin32

分析Qt原始碼一則想自己在開發學習中有積累,同時自己也一直有一種理念,使用她那麼就更深入的認識她。 如果有分析不正確的,還煩請各位看官指正。 事件分發器建立 在QCoreApplication建構函式中 if (!QCoreApplicationPrivate

lodash原始碼分析isArguments

lodash原始碼分析之isArguments 有人命中註定要過平庸的生活,默默無聞,因為他們經歷了痛苦或不幸;有人卻故意這樣做,那是因為他們得到的幸福超過了他們的承受能力。 ——卡爾維諾《煙雲》 本文為讀 lodash 原始碼的第二十一篇,後續文章會更新到這個倉庫中,歡迎 star:poc

Netty原始碼分析LengthFieldBasedFrameDecoder

拆包的原理 關於拆包原理的上一篇博文 netty原始碼分析之拆包器的奧祕 中已詳細闡述,這裡簡單總結下:netty的拆包過程和自己寫手工拆包並沒有什麼不同,都是將位元組累加到一個容器裡面,判斷當前累加的位元組資料是否達到了一個包的大小,達到一個包大小就拆開,進而傳遞到上層業務解碼handler 之所以ne

illuminate/routing 原始碼分析註冊路由

我們知道,在 Laravel 世界裡,外界傳進來一個 Request 時,會被 Kernel 處理並返回給外界一個 Response。Kernel 在處理 Request 時,會呼叫 illuminate/routing 包提供的路由功能,來根據當前的 Request,轉發到對應的執行邏輯(執行邏輯的形式可以