# 区块链技术之环签名

1. 无法撤销单个签名的匿名性;
2. 任何用户组都可以作为一个组使用，无需额外设置。

（1）密钥生成。为环中每个成员产生一个密钥对(公钥PKi,私钥SKi)。

（2）签名。签名者用自己的私钥和任意n个环成员(包括自己)的公钥为消息m生成签名a。

（3）签名验证。验证者根据环签名和消息m,验证签名是否为环中成员所签,如果有效就接收,否则丢弃。

Python实现样例

import os, hashlib, random, Crypto.PublicKey.RSA

class ring:
def __init__(self, k, L=1024):
self.k = k
self.l = L
self.n = len(k)
self.q = 1 << (L - 1)

def sign(self, m, z):
self.permut(m)
s = [None] * self.n
u = random.randint(0, self.q)
c = v = self.E(u)
for i in (range(z+1, self.n) + range(z)):
s[i] = random.randint(0, self.q)
e = self.g(s[i], self.k[i].e, self.k[i].n)
v = self.E(v^e)
if (i+1) % self.n == 0:
c = v
s[z] = self.g(v^u, self.k[z].d, self.k[z].n)
return [c] + s

def verify(self, m, X):
self.permut(m)
def _f(i):
return self.g(X[i+1], self.k[i].e, self.k[i].n)
y = map(_f, range(len(X)-1))
def _g(x, i):
return self.E(x^y[i])
r = reduce(_g, range(self.n), X[0])
return r == X[0]

def permut(self, m):
self.p = int(hashlib.sha1('%s' % m).hexdigest(),16)

def E(self, x):
msg = '%s%s' % (x, self.p)
return int(hashlib.sha1(msg).hexdigest(), 16)

def g(self, x, e, n):
q, r = divmod(x, n)
if ((q + 1) * n) <= ((1 << self.l) - 1):
rslt = q * n + pow(r, e, n)
else:
rslt = x
return rslt

size = 4
msg1, msg2 = 'hello', 'world!'

def _rn(_):
return Crypto.PublicKey.RSA.generate(1024, os.urandom)

key = map(_rn, range(size))
r = ring(key)
for i in range(size):
s1 = r.sign(msg1, i)
s2 = r.sign(msg2, i)
assert r.verify(msg1, s1) and r.verify(msg2, s2) and not r.verify(msg1, s2)

go实现样例

import (
"bytes"
"crypto/elliptic"
"crypto/sha256"
"fmt"
"io"
"math/big"
"sync"
)

type Curve interface {
// Params returns the parameters for the curve.
Params() *CurveParams
// IsOnCurve reports whether the given (x,y) lies on the curve.
IsOnCurve(x, y *big.Int) bool
// Add returns the sum of (x1,y1) and (x2,y2)
Add(x1, y1, x2, y2 *big.Int) (x, y *big.Int)
// Double returns 2*(x,y)
Double(x1, y1 *big.Int) (x, y *big.Int)
// ScalarMult returns k*(Bx,By) where k is a number in big-endian form.
ScalarMult(x1, y1 *big.Int, k []byte) (x, y *big.Int)
// ScalarBaseMult returns k*G, where G is the base point of the group
// and k is an integer in big-endian form.
ScalarBaseMult(k []byte) (x, y *big.Int)
}
type CurveParams struct {
P       *big.Int // the order of the underlying field
N       *big.Int // the order of the base point
B       *big.Int // the constant of the curve equation
Gx, Gy  *big.Int // (x,y) of the base point
BitSize int      // the size of the underlying field
Name    string   // the canonical name of the curve
}

Double函数是自加，几何上为切线求另一交点。
ScalarMult是点的数乘，注意就是离散对数里面的幂。
ScalarBaseMult是基点的数乘，供方便用。

type PublicKey struct {
elliptic.Curve
X, Y *big.Int
}
type PrivateKey struct {
PublicKey
D *big.Int
}

type PublicKeyRing struct {
Ring []PublicKey
}

func NewPublicKeyRing(cap uint) *PublicKeyRing {
return &PublicKeyRing{make([]PublicKey, 0, cap)}
}

func (r *PublicKeyRing) Add(pub PublicKey) {
r.Ring = append(r.Ring, pub)
}

func (r *PublicKeyRing) Len() int {
return len(r.Ring)
}

func (r *PublicKeyRing) Bytes() (b []byte) {
for _, pub := range r.Ring {
b = append(b, pub.X.Bytes()...)
b = append(b, pub.Y.Bytes()...)
}
return
}
var one = new(big.Int).SetInt64(1)

func randFieldElement(c elliptic.Curve, rand io.Reader) (k *big.Int, err error) {
params := c.Params()
b := make([]byte, params.BitSize/8+8)
if err != nil {
return
}

k = new(big.Int).SetBytes(b)
n := new(big.Int).Sub(params.N, one)
k.Mod(k, n)
return
}

func GenerateKey(c elliptic.Curve, rand io.Reader) (priv *PrivateKey, err error) {
k, err := randFieldElement(c, rand)
if err != nil {
return
}

priv = new(PrivateKey)
priv.PublicKey.Curve = c
priv.D = k
priv.PublicKey.X, priv.PublicKey.Y = c.ScalarBaseMult(k.Bytes())
return
}

type RingSign struct {
X, Y *big.Int
C, T []*big.Int
}

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客