目錄git
P256對應的橢圓曲線是:
\[ y^2=x^3-3x+b \]github
假設k是私鑰,G是公鑰(\(g^k\))
m:表示已知的公共信息,好比當前要出的塊號100app
思路也很簡單,將Hash(m)(注意是256位hash)做爲曲線上的X,而後帶入上述橢圓曲線公式,求出相應的Y便可.google
這個也很簡答,就是Hash(...)%q便可.spa
\[ h=H_1(m) \\ v=VRF_k(m)=h^k \]
這就是所謂的可驗證隨機數,那麼怎麼讓他可驗證呢?code
隨機生成一個r,而後計算
\[ s=H_2(g,h,G,v,g^r,h^r) \\ t=r-sk (mod p) \]orm
而後把(v,s,t)一塊兒打包發給驗證方,three
上述信息中已知的有:ip
\[ g^r =g^{t+ks} =g^t \cdot g^{ks} =g^t \cdot {g^k}^s =g^t \cdot G^s \]
\[ h^r =h^{t+ks} =h^t \cdot h^{ks} =h^t \cdot {h^k}^s =h^t \cdot v^s \]get
雖然驗證人不知道k,也不知道r,可是知道h,g,G,v,s,t因此他能夠計算出\(s2=H_2(g,h,G,v,g^t \cdot G^s,h^t \cdot v^s)\)
而後驗證s2是否和s相等,若是相等,那就是k持有人按照規則計算出的隨機數
谷歌給出的例子是針對P256的,可是不管是比特幣仍是以太坊及其衍生鏈,採用的都是S256曲線. 那麼通過簡單的改造就能夠在S256曲線上使用VRF
將使用的P256直接換成S256
//curve = elliptic.P256() curve=btcec.S256() params = curve.Params()
前面提到H1其實是把任意信息映射到曲線上的點,P256方案採用的曲線是
\(y^2=x^3-3x+b\),而S256曲線是\(y^2=x^3+b\),稍微有一些區別,所以計算\(y^2\)的方法要修改
// Use the curve equation to calculate y² given x. // only applies to curves of the form y² = x³ - 3x + b. func y2(curve *elliptic.CurveParams, x *big.Int) *big.Int { // y² = x³ - 3x + b x3 := new(big.Int).Mul(x, x) x3.Mul(x3, x) //threeX := new(big.Int).Lsh(x, 1) //threeX.Add(threeX, x) // //x3.Sub(x3, threeX) x3.Add(x3, curve.B) x3.Mod(x3, curve.P) return x3 }
P256代碼中的ScalarMult和ScalarBaseMult都是使用的params上的方法,這個方法是在go標準庫中的.標準庫針對的橢圓曲線並非S256,而是\(y^2=x^3+b\),所以不能使用,要替換成curve上的想用方法.
把params.ScalarBaseMult替換成curve.ScalarBaseMult
把params.ScalarMult替換成curve.ScalarMult