本文介绍了Pedersen哈希算法,它通过组合椭圆曲线上的点来实现加密哈希过程,使其在零知识证明(ZKP)系统中特别有用。文章解释了Pedersen哈希的基本原理,包括如何将输入消息分解为多个块,并使用这些块基于生成器点生成一系列椭圆曲线点,最后将生成的点相加得到哈希值。
密码学哈希过程通常涉及某种形式的复杂操作,例如挤压和调整数据位,以及缺少代数方法的内容。另一方面,Pedersen哈希涉及几个椭圆曲线点的组合。这使得它们在零知识证明(ZKP)系统中实现哈希函数非常有用。
Pedersen哈希基于Torben P Pedersen关于承诺方案的工作 [1]:
在Zcash团队在其Sapling协议的zk-SNARK电路中实现它之后,该方法重新获得了关注[ 这里]:
以最简单的形式,Pedersen哈希基本上是一种将值的哈希固定到椭圆曲线点的方法:
Hash(x) = x.G
其中G是椭圆曲线上的一个点。 这样,我们应该无法将x.G的值反转回x。以更完整的形式,我们可以将输入消息分成_k_块(m 1, m 2 … mk),然后使用这些块基于多个生成器点(G 1, G 2 … Gk)生成一系列椭圆曲线点。 然后,哈希是所创建点的总和:
H = m 1. G 1+ m 2. G 2+ m 3. G 3
如果我们使用三个块,则消息分为三个:
免费加入Medium,获取该作者的最新信息。
m = m 1|| m 2|| m 3
然后,我们生成三个间隔良好的生成器点:
G 1, G 2, G 3
Pedersen哈希是:
Hash =( m 1). G 1+( m 2). G 2+( m 3). G 3
其中(m 1). G 1,(m 2). G 2和(m 3). G 3是曲线上的点。让我们在Tiny Jubjub曲线上取三个点[ 在曲线上查找点]:
gx1,_ := new(big.Int).SetString("18930368022820495955728484915491405972470733850014661777449844430438130630919",10 )
gy1,_ := new(big.Int).SetString("0",10)
gx2,_ := new(big.Int).SetString("12576558175125128246374296641007938322302911659474853157208587689687229831284",10 )
gy2,_ := new(big.Int).SetString("3",10)
gx3,_ := new(big.Int).SetString("18869612826929474874643025262839512853875949931275176402223244870011103237908",10 )
gy3,_ := new(big.Int).SetString("5",10)
然后我们可以使用以下方法计算哈希[ 这里]:
package main
import (
"fmt"
"github.com/iden3/go-iden3-crypto/v2/babyjub"
"math/big"
"encoding/hex"
"os"
)
func splitMessage(inStr string, size int) []string { // 分割消息
var elements []string
elementSize := len(inStr) / size
for i := 0; i < size; i++ {
start := i * elementSize
end := start + elementSize
if i == size-1 {
end = len(inStr)
}
elements = append(elements, inStr[start:end])
}
return elements
}
func main() {
// Baby Jubjub曲线上的三个生成器值:
//19763400273586758549882294695966112539108188722254631372974345487113325868230, 13
//12576558175125128246374296641007938322302911659474853157208587689687229831284, 3
//18869612826929474874643025262839512853875949931275176402223244870011103237908, 5
str:="Testing 123"
argCount := len(os.Args[1:])
if (argCount>0) {str= string(os.Args[1])}
fmt.Printf("Input message: %s\n\n",str) // 输入消息
value := hex.EncodeToString([]byte(str))
res:= splitMessage(value,3)
gx1,_ := new(big.Int).SetString("19763400273586758549882294695966112539108188722254631372974345487113325868230",10 )
gy1,_ := new(big.Int).SetString("13",10)
gx2,_ := new(big.Int).SetString("12576558175125128246374296641007938322302911659474853157208587689687229831284",10 )
gy2,_ := new(big.Int).SetString("3",10)
gx3,_ := new(big.Int).SetString("18869612826929474874643025262839512853875949931275176402223244870011103237908",10 )
gy3,_ := new(big.Int).SetString("5",10)
G1 := &babyjub.Point{X: gx1, Y: gy1}
G2 := &babyjub.Point{X: gx2, Y: gy2}
G3 := &babyjub.Point{X: gx3, Y: gy3}
fmt.Printf("G1 (%s, %s)\n",G1.X.String(),G1.Y.String())
fmt.Printf("G2 (%s, %s)\n",G2.X.String(),G2.Y.String())
fmt.Printf("G3 (%s, %s)\n\n",G3.X.String(),G3.Y.String())
m_1,_:=hex.DecodeString(res[0])
m_2,_:=hex.DecodeString(res[1])
m_3,_:=hex.DecodeString(res[2])
M1:=new(big.Int).SetBytes(m_1)
M2:=new(big.Int).SetBytes(m_2)
M3:=new(big.Int).SetBytes(m_3)
M1_G1 := babyjub.NewPoint().Mul(M1,G1)
M2_G2 := babyjub.NewPoint().Mul(M2,G2)
M3_G3 := babyjub.NewPoint().Mul(M3,G3)
M1_G1_M2_G2 := babyjub.NewPoint().Projective().Add(M1_G1.Projective(),M2_G2.Projective())
M1_G1_M2_G2_M3_G3 := babyjub.NewPoint().Projective().Add(M1_G1_M2_G2,M3_G3.Projective())
fmt.Printf("(%d).G1 Point (%s, %s)\n",M1,M1_G1.X.String(),M1_G1.Y.String())
fmt.Printf("(%d).G2 Point (%s, %s)\n",M2,M2_G2.X.String(),M2_G2.Y.String())
fmt.Printf("(%d).G3 Point (%s, %s)\n\n",M3,M3_G3.X.String(),M3_G3.Y.String())
fmt.Printf("Result: (%s, %s)\n\n",M1_G1_M2_G2_M3_G3.X.String(),M1_G1_M2_G2_M3_G3.Y.String())
fmt.Printf("Pedersen Hash: %s\n",M1_G1_M2_G2_M3_G3.X.String()) // Pedersen哈希
}
结果是 [ 这里]:
Input message (in hex): 010203040506070809
G1 (19763400273586758549882294695966112539108188722254631372974345487113325868230, 13)
G2 (12576558175125128246374296641007938322302911659474853157208587689687229831284, 3)
G3 (18869612826929474874643025262839512853875949931275176402223244870011103237908, 5)
(66051).G1 Point (16037773783835146438558403421260836675868272902364849599426875451057520106906, 14728403640743494614641112385959960394789183729111213630842711014573474773378)
(263430).G2 Point (11852499477985754981114582499827808786287610741986412935345795152171632055691, 2674722056485308817737914684425248014914348605929003485370677590616611371783)
(460809).G3 Point (7621534404334108830225350985637201742729050263412910533478640032004698408257, 3768640800306573992890050298007966758509235918251221830887953108815318470075)
Result: (8246050116631628695869530651297899884448852706174930565536327904583775502268, 21660911736906458468630355032769751803544552633662219825808465470014769680600)
Pedersen Hash: 8246050116631628695869530651297899884448852706174930565536327904583775502268
当然,在现实生活中,我们会将生成器点分隔开。
[1] Pedersen, T. P. (1991, August). Non-interactive and information-theoretic secure verifiable secret sharing. In 年度国际密码学会议 (pp. 129–140). Berlin, Heidelberg: Springer Berlin Heidelberg.
- 原文链接: billatnapier.medium.com/...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!