func hashToInt(hash []byte, c elliptic.Curve) *big.Int {
orderBits := c.Params().N.BitLen()
orderBytes := (orderBits + 7) / 8
if len(hash) > orderBytes {
hash = hash[:orderBytes]
}
ret := new(big.Int).SetBytes(hash)
excess := len(hash)*8 - orderBits
if excess > 0 {
ret.Rsh(ret, uint(excess))
}
return ret
}
这一段是哈希字符串转整数,这段作者有一个附加声明:
// hashToInt converts a hash value to an integer. There is some disagreement
// about how this is done. [NSA] suggests that this is done in the obvious
// manner, but [SECG] truncates the hash to the bit-length of the curve order
// first. We follow [SECG] because that's what OpenSSL does. Additionally,
// OpenSSL right shifts excess bits from the number if the hash is too large
// and we mirror that too.
将哈希值截断到曲线的阶,简化了后面的乘法计算,不过签名验证方这个函数要统一。
func hashG(c elliptic.Curve, m []byte) (hx, hy *big.Int) {
h := sha256.New()
h.Write(m)
d := h.Sum(nil)
hx, hy = c.ScalarBaseMult(d)
return
}
求消息的哈希字符串,并映射到椭圆曲线上,这个过程是【有争议的】,会导致匿名性消失。关于如何改进我正在考虑。
func hashAllq(mR []byte, ax, ay, bx, by []*big.Int) (hash *big.Int) {
h := sha256.New()
h.Write(mR)
for i := 0; i < len(ax); i++ {
h.Write(ax[i].Bytes())
h.Write(ay[i].Bytes())
h.Write(bx[i].Bytes())
h.Write(by[i].Bytes())
}
hash = new(big.Int).SetBytes(h.Sum(nil))
return
}
这是与论文 H′ H ′ 函数对应的函数,将多个元素加入后进行验证可以理解为每一个都与期望的结果相同。
func Sign(rand io.Reader, priv *PrivateKey, R *PublicKeyRing, m []byte) (rs *RingSign, err error) {
s := R.Len()
ax := make([]*big.Int, s, s)
ay := make([]*big.Int, s, s)
bx := make([]*big.Int, s, s)
by := make([]*big.Int, s, s)
c := make([]*big.Int, s, s)
t := make([]*big.Int, s, s)
pub := priv.PublicKey
curve := pub.Curve
N := curve.Params().N //基点的阶(请查阅官方库)
mR := append(m, R.Bytes()...) //m是消息,R是环
hx, hy := hashG(curve, mR) // H(mR)
var id int
var wg sync.WaitGroup //阻塞主线程的执行,直到所有的goroutine执行完成
sum := new(big.Int).SetInt64(0)
for j := 0; j < s; j++ {
wg.Add(1)
go func(j int) { //go用于并行 以并发的方式调用匿名函数func
defer wg.Done() //这几个线程还要好好研究下
c[j], err = randFieldElement(curve, rand)
if err != nil {
return
}
t[j], err = randFieldElement(curve, rand) //随机数,如果是本身,随机数有效,如果不是本身,这个随机数无效,个人觉得可以改进。
if err != nil {
return
}
//补注,这里椭圆曲线上的乘法其实是点加法,这里的幂其实是离散点乘法。
//err是错误捕捉
if R.Ring[j] == pub { //当前处理的是自己的
id = j
rb := t[j].Bytes()
ax[id], ay[id] = curve.ScalarBaseMult(rb) // g^r //g是一个基点,这个椭圆曲线的阶应该足够大
bx[id], by[id] = curve.ScalarMult(hx, hy, rb) // H(mR)^r
} else {
ax1, ay1 := curve.ScalarBaseMult(t[j].Bytes()) // g^tj
ax2, ay2 := curve.ScalarMult(R.Ring[j].X, R.Ring[j].Y, c[j].Bytes()) // yj^cj
ax[j], ay[j] = curve.Add(ax1, ay1, ax2, ay2) //☆这里再重点研读一下//就是点加法,论文里写的是乘法。
//这也提醒我们,除了乘方要变成乘法之外,乘法要变成加法。
w := new(big.Int)
w.Mul(priv.D, c[j])
w.Add(w, t[j]) //(xi*cj+tj)
w.Mod(w, N)
bx[j], by[j] = curve.ScalarMult(hx, hy, w.Bytes()) // H(mR)^(xi*cj+tj)
// TODO may need to lock on sum object.
sum.Add(sum, c[j]) // Sum needed in Step 3 of the algorithm//cj只是随机数字
}
}(j)
}
wg.Wait()
// Step 3, part 1: cid = H(m,R,{a,b}) - sum(cj) mod N
hashmRab := hashAllq(mR, ax, ay, bx, by)
// hashmRab := hashAllqc(curve, mR, ax, ay, bx, by)
c[id].Sub(hashmRab, sum) //id是自己,自己的签名要减去所有其他人的签名,这样所有人加起来就是随机数(全哈希)
c[id].Mod(c[id], N)
// Step 3, part 2: tid = ri - cid * xi mod N
cx := new(big.Int)
cx.Mul(priv.D, c[id]) //D就是x
t[id].Sub(t[id], cx) // here t[id] = ri (initialized inside the for-loop above)
t[id].Mod(t[id], N)
hsx, hsy := curve.ScalarMult(hx, hy, priv.D.Bytes()) // Step 4: H(mR)^xi
return &RingSign{hsx, hsy, c, t}, nil
}
签名函数,这里比较长就直接注释了。这个签名的过程如下:
首先约定私钥 xi∈Zq x i ∈ Z q 及公钥