前言
在密码学中,环签名是一种数字签名,其可以由每个具有密钥的一组用户的任何成员完成。因此,使用环签名签名的消息由特定人群中的某一人签署。环签名的一个安全属性是若要确定哪个组成员的密钥用于产生签名在计算上是不可行的。环签名与群签名类似,但在两个关键方面有所不同:
- 无法撤销单个签名的匿名性;
- 任何用户组都可以作为一个组使用,无需额外设置。
环签名技术由Ron Rivest, Adi Shamir, 和 Yael Tauman发明的,于2001发表出来的。环签名得名于其环状结构签名算法。
对于区块链方面多技术,我还是建议大家多看英文文档,多利用Google来搜索技术文章。
怎么搭建自己专属V-P-N来访问Google,请看我之前发的文章: 新人如何快速搭建自己的个人网站以及自己专属V-P-N代理
定义
假设有一组用户,每个人都有公钥和私钥对,(P1, S1), (P2, S2), ..., (Pn, Sn)。用户i可以基于消息m计算一个环签名σ ,输入参数为(m, Si, P1, ..., Pn)。如果给定参数σ, m以及所有的公钥(P1, ..., Pn),任何人都可以检查该环签名的合法性。如果环签名是正确的,那么它应该可以通过刚才的验证。另外,如果没有当前用户组中任何一个用户的私钥,任何人应该是不太可能基于任何组消息来创建一个合法的环签名。
环签名满足的性质
- 无条件匿名性:攻-击-者者无法确定签名是由环中哪个成员生成,即使在获得环成员私钥的情况下,概率也不超过1/n。
- 正确性:签名必需能被所有其他人验证。
- 不可伪造性:环中其他成员不能伪造真实签名者签名,外部攻-击-者者即使在获得某个有效环签名的基础上,也不能为消息m伪造一个签名。
环签名实现:
(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
签名并验证两个由4个用户组成的环签名消息:
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语音的实现版本请参考 --> 用Go语言实现环签名的签名和验证
对于区块链方面多技术,我还是建议大家多看英文文档,多利用Google来搜索技术文章。
怎么搭建自己专属V-P-N来访问Google,请看我之前发的文章: 新人如何快速搭建自己的个人网站以及自己专属V-P-N代理
原文地址:http://blog.51cto.com/huihua/2170409