Chameleon Hash Functions

Chameleon Hash Functions(变色龙哈希)


前言

提示:这篇博客是我在阅读论文后根据自己的理解写的,可能有些翻译不准确,欢迎大家指正!


提示:以下是本篇文章正文内容,下面案例可供参考

一、变色龙Has是什么?

传统哈希函数的难以找到碰撞,变色龙哈希可以人为的设一个“弱点”或者“后门”:掌握了这个后门就可以轻松的找到哈希碰撞。
​ 这种设计在一定程度上破坏了哈希函数的两个碰撞性的特点,同时,也破坏了基于哈希函数的区块链的不可篡改的特性,但是也扩大了区块链的应用场景,而且对于不知道门限的普通用户来说,想要找到碰撞依然是不可行的,也就是说,变色龙哈希的安全性也是可以保障的,对于持有“后门”的管理人员,如果其随意篡改区块,也是可以通过验证两个区块的哈希是否相等来验证。

用户R的公钥表示为 H K R HK_R HKR

私钥(陷门) C H R CH_R CHR, 公钥 H K R HK_R HKR定义了一个变色龙散列函数, c h a m − h a s h R ( ) cham-hash_R() chamhashR()

在输入消息m和随机字符串r时,该函数生成哈希值 c h a m − h a s h R ( m , r ) cham-hash_R(m,r) chamhashR(m,r),满足以下属性:

  • 抗碰撞: 在输入公钥HKR时,没有 m 1 = m 2 m_1 = m_2 m1=m2算法可以对 c h a m − h a s h R ( m 1 , r 1 ) = c h a m − h a s h R ( m 2 , r 2 ) cham-hash_R(m_1,r_1) = cham-hash_R(m_2,r_2) chamhashR(m1,r1)=chamhashR(m2,r2),除非概率可以忽略不计。
  • 陷门碰撞: 在输入秘钥 C H R CH_R CHR时,任意对 m 1 ; r 1 m_1;r_1 m1r1都可以找到值 m 2 , r 2 m_2,r_2 m2,r2,使得 c h a m − h a s h R ( m 1 , r 1 ) = c h a m − h a s h R ( m 2 , r 2 ) cham-hash_R(m_1,r_1) = cham-hash_R(m_2,r_2) chamhashR(m1,r1)=chamhashR(m2,r2)
  • 统一: 特别是,从随机选择的r中看到 c h a m − h a s h R ( m , r ) cham-hash_R(m,r) chamhashR(m,r)),对m一无所知,以要求上述分布对于所有消息不一定相同,但在计算上无法区分

变色龙散列函数旨在作用于任意长的消息,并生成固定长度的输出。

示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。

二、变色龙散列基于无爪陷门排列

我们提出了一种基于无爪陷阱门排列的变色龙散列的一般结构,以及一种基于保理硬度的具体实现。 这个构造方法是最新的由Goldwasser、Micali和Rivest[GMR88]介绍,用于构建常规数字签名,并由Damgard[Dam87]用于构建抗碰撞哈希函数。 我们使用t的陷门信息,提供变色龙哈希的发现陷门碰撞特性。

在一个公共域上,如果它在计算上不可能从域中得到值x和y,使得 f 0 ( X ) = f 1 ( Y ) f_0(X)=f_1(Y) f0(X)=f1(Y),则称为(claw-free)。 一对排列 ( f 0 ( X ) ; f 1 ( X ) ) (f_0(X);f_1(X)) (f0(X)f1(X))

我们将长度k的消息m的二进制表示为m=m[1]…m[k],其中m[1]是消息第一位,m[k]是最后一位。

私钥: ( f 0 − 1 , f 1 − 2 ) (f_0^{-1},f_1^{-2}) (f01,f12)

公钥: ( f 0 , f 1 ) (f_0,f_1) (f0,f1)

消息:m=m[1]…m[k]

Hash:值 c h a m − h a s h ( f 0 , f 1 ) ( m , r ) = f m [ k ] ( . . . ( f m [ 2 ] ( f m [ 1 ] ( r 1 ) ) ) ) cham-hash_{(f_0, f_1)}(m,r)=f_{m[k]}(...(f_{m[2]}(f_{m[1]}(r_1)))) chamhash(f0,f1)(m,r)=fm[k](...(fm[2](fm[1](r1))))

对于消息 m 2 m_2 m2,求 r 2 : r_2: r2: f m 2 [ k ] − 1 ( . . . ( f m 2 [ 2 ] − 1 ( f m 2 [ 1 ] − 1 ( c h a m − h a s h ( m 1 , r 1 ) ) ) ) ) f_{m_2[k]}^{-1}(...(f_{m_2[2]}^{-1}(f_{m_2[1]}^{-1}(cham-hash(m_1,r_1))))) fm2[k]1(...(fm2[2]1(fm2[1]1(chamhash(m1,r1)))))

例子:

选择两个素数p=3, q = 7 , n = pq=21

f 0 ( x ) = x 2 m o d n f_0(x) = x ^2modn f0(x)=x2modn

f 1 ( x ) = 4 x 2 m o d n f_1(x) = 4x ^2modn f1(x)=4x2modn

D = { x ∣ ( x p ) = ( x q ) = 1 } D=\{x | (\frac{x}{p}) = (\frac{x}{q}) = 1\} D={x(px)=(qx)=1}保证x是模p,q的二次剩余


消息x1=101,r1=8

step1: 4 ∗ 8 ∗ 8 m o d 21 = 4 4 * 8 * 8 mod 21 = 4 488mod21=4

step2: 4 ∗ 4 m o d 21 = 16 4 * 4 mod 21 = 16 44mod21=16

step3: 4 ∗ 16 ∗ 16 m o d 21 = 16 4 * 16 * 16 mod 21 = 16 41616mod21=16

c h a m − h a s h ( f 0 , f 1 ) ( m , r ) = c h a m − h a s h ( f 0 , f 1 ) ( 101 , 8 ) = 16 cham-hash_{(f_0, f_1)}(m,r)=cham-hash_{(f_0, f_1)}(101,8)=16 chamhash(f0,f1)(m,r)=chamhash(f0,f1)(101,8)=16


消息x2=110,r2=?

step1: f 0 − 1 ( 16 ) = 4 f_0^{-1}(16) = 4 f01(16)=4

step2: f 1 − 1 ( 4 ) = 1 f_1^{-1}(4) = 1 f11(4)=1

step3: f 1 − 1 ( 1 ) = 4 f_1^{-1}(1) = 4 f11(1)=4

r 2 = 4 r_2=4 r2=4


验证:

消息x2=110,r2=4

step1: 4 ∗ 4 ∗ 4 m o d 21 = 1 4 * 4 * 4 mod 21 = 1 444mod21=1

step2: 4 m o d 21 = 4 4 mod 21 = 4 4mod21=4

step3: 4 ∗ 4 m o d 21 = 16 4 * 4 mod 21 = 16 44mod21=16

c h a m − h a s h ( f 0 , f 1 ) ( m , r ) = c h a m − h a s h ( f 0 , f 1 ) ( 110 , 4 ) = 16 cham-hash_{(f_0, f_1)}(m,r)=cham-hash_{(f_0, f_1)}(110,4)=16 chamhash(f0,f1)(m,r)=chamhash(f0,f1)(110,4)=16


三、 基于离散对数的变色龙哈希

Hugo Krawczky 和 Tal Rabin 在2000年提出了变色龙哈希方案,具体方案描述如下:

  1. Setup(λ):输入安全性参数λ ,构造满足安全性参数λ 的大素数p,q,其中p,q满足p=kq+1,选取乘法循环群 Z p ∗ Z^{*}_p Zp中阶为q的元素g,

    输出公共参数pp=(p,q,g);

  2. KeyGen(pp):输入公共参数pp,在乘法循环群 Z p ∗ Z^{*}_p Zp中随机选择指数x,计算 h = g x h=g^x h=gx,最后得到私钥CK=x公钥HK=h

  3. Hash(HK,m,r):输入公钥HK,消息m,随机数r,其中m,r均为 Z p ∗ Z^{*}_p Zp中元素,输出变色龙哈希值 C H = g m h r m o d p CH=g^mh^r mod p CH=gmhrmodp;

  4. Forge(CK,m,r,m’): 输入私钥,CH=x,消息m,随机数r,消息m’,其中m,r, m’,均为 Z p ∗ Z^{*}_p Zp中的元素,

    根据 C H = g m h r m o d p = g m ‘ h r ‘ m o d p CH=g^mh^r mod p=g^{m^`}h^{r^`}mod p CH=gmhrmodp=gmhrmodp,可得 m + x r = ( m ‘ + x r ‘ ) m o d p m+xr=(m^`+xr^`) mod p m+xr=(m+xr)modp,继而可计算出 r ’ = ( m − m ’ + x r ) x − 1 m o d p r’=(m-m’+xr)x^{-1} mod p r=(mm+xr)x1modp

**参数选择:**p,q满足p=kq+1,乘法循环群 Z p ∗ Z^{*}_p Zp中阶为q的元素g

私钥: C H = x CH=x CH=x

公钥: H K = h = g x HK=h=g^x HK=h=gx

**消息:**m

**随机数:**r

变色龙哈希值 C H = g m h r m o d p CH=g^mh^r mod p CH=gmhrmodp;

消息: m 2 m_2 m2

目标: C H = g m h r m o d p = g m ‘ h r ‘ m o d p CH=g^mh^r mod p=g^{m^`}h^{r^`}mod p CH=gmhrmodp=gmhrmodp,

​ 可得 m + x r = ( m ‘ + x r ‘ ) m o d p m+xr=(m^`+xr^`) mod p m+xr=(m+xr)modp,

​ 继而可计算出 r ’ = ( m − m ’ + x r ) x − 1 m o d p r’=(m-m’+xr)x^{-1} mod p r=(mm+xr)x1modp

私钥:x=2, g=3,q=3,p=kq+1=13

公钥: g x = 3 2 m o d 13 = 9 g^x=3^2mod13=9 gx=32mod13=9


m = 2 , r = 1 m=2,r=1 m=2,r=1

c h a m − h a s h ( 4 , 2 ) = g m h r = 3 2 9 1 m o d 13 = 81 m o d 13 = 3 cham-hash(4,2)=g^mh^r = 3^2 9^{1}mod13=81mod13=3 chamhash(4,2)=gmhr=3291mod13=81mod13=3


m ‘ = 0 m^`=0 m=0

r ’ = ( m − m ’ + x r ) x − 1 m o d p = 4 ∗ 2 − 1 m o d 13 = 2 r’=(m-m’+xr)x^{-1} mod p =4*2^{-1}mod 13=2 r=(mm+xr)x1modp=421mod13=2


验证:

c h a m − h a s h ( 0 , 2 ) = g m h r = 3 0 9 2 m o d 13 = 81 m o d 13 = 3 cham-hash(0,2)=g^mh^r = 3^0 9^{2}mod13=81mod13=3 chamhash(0,2)=gmhr=3092mod13=81mod13=3

c h a m − h a s h ( 2 , 1 ) = c h a m − h a s h ( 0 , 2 ) cham-hash(2,1)=cham-hash(0,2) chamhash(2,1)=chamhash(0,2)


四、数字签名

变色龙哈希函数非常有意思。传统加密哈希函数是很难找到碰撞的。变色龙哈希函数可以人为设下一个“弱点”:掌握了它就能轻松找到碰撞。就好比一扇上锁的门,有对应的钥匙就能通过。

但是有谁吃饱了撑的故意设计弱化的哈希函数呢?这就要涉及到一个伴随因特网自始至终的信任问题,电子签名。传统电子签名过程是先用哈希函数把文件过一遍生成摘要,再用非对称加密里的私钥对摘要进行签名,这样其他人就能用对应的公钥验证文件的哈希有没有变化。如果哈希没变化,那么文件就没被更改。

但是这种设计有它的不足。假设小明和小红达成协议,小明将家族产业10%股份转让给小红。签了合同小名很担心啊,如果小红把这件事告诉别人怎么办?这时候就可以用变色龙函数进行签名。小红生成一个只有她才能找到碰撞的函数交给小明,小明再用这个函数来签电子文档。这下小红把签名后的文件丢给大家也没人相信她了。为什么呢?她掌握着哈希函数的弱点,可以随便生成哈希碰撞啊。她把10%股份改成99%都能保证哈希不会变,进而创造出新文件本来就是小明签的这种假象。因此出自小红之手的文件可信度为零。这个特性叫non-transferability,即两者之间达成的信任不能转到第三方。

“你知道的太多了” 此时此刻成了真正的包袱。

问题来了,小明抵赖怎么破?如果小明死死咬定转让10%股份是小红伪造,事实上只有1%呢?事实上小明也不能信口开河,他得提供对应的证据。证据就是哈希碰撞。假设双方达成的最初合同是A,而小红将其篡改成了相同哈希的A’,那么小明看到A’这份伪证之后一定能拿出最早那个A来并表明A和A’形成哈希碰撞,否则A’就是真货了。因为正常情况下小明无论如何也找不到碰撞,他就不能抵赖。这个特性叫non-repudiation。

首先, 变色龙签名具有不可传递性: 其合法性只能由签名者所指定的接收者来验证, 而其他任何人都不能确定该签名是由签名者所签的, 还是由指定接收者伪造的. 其次,变色龙签名具有不可伪造性: 对于一个伪造的变色龙签名,合法的签名者能够提供证据表明该伪造签名的不合法性. 再者, 变色龙签名具有不可否认性: 对于合法的变色龙签名, 其签名者并不能提供此类证明以开脱责任. 既然变色龙签名能够同时提供不可否认性, 不可伪造性和不可传递性, 所以变色龙签名是一种比较理想的指定验证者签名. 构造变色龙签名的主要工具是变色龙哈希函数. 更具体地讲, 变色龙签名的构造遵循了著名的先哈希再签名的范例(hash-and-sign paradigm), 但是稍有不同. 也就是说, 用来计算消息摘要的是变色龙哈希函数, 而不是普通的哈希函数; 用来计算签名的则是一个安全的数字签名算法. 变色龙哈希函数是一种带陷门的抗碰撞哈希函数: 对于知道其陷门的用户来说, 寻找该哈希函数的碰撞是非常容易的; 而对于不知道其陷门的用户来说, 这种哈希函数与一个标准的哈希函数一样是抗碰撞的. 既然变色龙签名是作用到消息摘要的一个函数, 而此消息摘要又是一个变色龙哈希值, 且陷门属于指定接收者, 所以指定验证者可以把一个变色龙签名变成是其他消息的签名.

水印

五、Github源码

水印
单一帧添加我发哥的水印

运行代码:

calculating...

q= 7076412147999344709848440438228952875717
p= 34377210214980816600443723648916253070233187
g= 4003
SK= 5436429092544353106088843605389875260377
PK= 7725592492408161713638690353041010273814722

msg1= i sent first message
rand1= 1674181499801353348207492416622746708885
CH= 22072510447255878935850254532181551499522989

msg2= second message
rand2= 610322978229803970975139617333478732290
newCH= 22072510447255878935850254532181551499522989


说明:使用下面的源码,需要安装一个素数的库,这里需要再安装一个VC的环境,否则会报错

  • Github源码地址:https://github.com/Zipzapztc/ChameleonHash
  • 本文参考文献: Krawczyk H M , Rabin T D . Chameleon hashing and signatures: US 2000.

我给大家整理了一下,做了一个集成,如下:

# n个用户,n个PK,SK,r,CH=g^m*h1^r1*h2^r2……hn^rn mod p

# Setup(),KeyGen(),ChameleonHash(),Forge()四个函数

import random
from pyunit_prime import get_large_prime_length  # 随机生成指定长度大素数
from pyunit_prime import is_prime  # 判断素数
from pyunit_prime import prime_range  # 输出指定区间素数
import math

random.seed(45687)
# p=0
# q=0
p = 52650424227621396410011
q = 83572101948605391127
g = 358
length = 20
def primeFactorization(length):  # 分解质因数
    # global p,q
    p, q = 0, 0
    q = get_large_prime_length(length)
    while True:
        d = random.randint(2, 10000)
        if d % 2 == 0:
            p = q * d + 1
            if is_prime(p) == True:
                break
            else:
                continue
        else:
            continue
    primeList = prime_range(2, int(math.sqrt(d)))
    result = [[0, 0] for i in range(len(primeList))]
    for i in range(len(primeList)):
        result[i][0] = primeList[i]
        while d % primeList[i] == 0:
            result[i][1] += 1
            d = d // primeList[i]
    if d != 1:
        result.append([d, 1])
    result.append([q, 1])
    return result, p, q


def quickPower(a, b, c):  # 快速幂,a^b mod c
    result = 1
    while b > 0:
        if b % 2 == 1:
            result = result * a % c
        a = a * a % c
        b >>= 1
    return result


def getGenerator(result, p, q):  # get g
    generator = random.randint(1, 1000)
    while True:
        if quickPower(generator, q, p) != 1:
            generator += 1
        else:
            for i in range(len(result)):
                if quickPower(generator, int((p - 1) / result[i][0]), p) == 1:
                    break
            if i != len(result) - 1:
                generator += 1
            else:
                break
    return generator


def Setup(length):
    factorization, p, q = primeFactorization(length)
    g = getGenerator(factorization, p, q)
    return p, q, g


def getSecretKey(n, q):  # get SKlist,x1,x2……xn
    SKlist = []
    for _ in range(n):
        SKlist.append(random.randint(1, q))
    return SKlist


def getPublicKey(g,x):                             #get PK,h
    h=quickPower(g,x,p)
    return h


def KeyGen(p, q, g, n):
    SKlist = getSecretKey(n, q)
    PKlist = getPublicKey(g, SKlist, n, p)
    return SKlist, PKlist


def getr(n, q):  # rlist,r1,r2……rn
    rlist = []
    for _ in range(n):
        rlist.append(random.randint(1, q))
    return rlist


def treatMSG(msg):  # 处理消息msg为整数
    newmsg = ''
    for i in msg:
        newmsg += str(ord(i))
    return int(newmsg)


def ChameleonHash(PK,g,m,r):                       #变色龙哈希
    CH=quickPower(g,m,p)*quickPower(PK,r,p)%p
    return CH


def exgcd(a, b):  # 扩展欧几里得
    if b == 0:
        return 1, 0, a
    else:
        x, y, gcd = exgcd(b, a % b)
        x, y = y, (x - (a // b) * y)
        return x, y, gcd


def Forge(SK,m1,r1,m2):                            #求r'
    x,y,gcd=exgcd(SK,q)
    result=x*(m1-m2+SK*r1)%q
    return result


def CHhashAPI(msg1, msg2, SK, rand1):
    PK = getPublicKey(g, SK)
    newmsg1 = treatMSG(msg1)
    newmsg2 = treatMSG(msg2)
    rand2 = Forge(SK, newmsg1, rand1, newmsg2)
    newCH = ChameleonHash(PK, g, newmsg2, rand2)
    return {"CH": newCH, "rand": rand2}

def CH(msg, SK):
    PK = getPublicKey(g, SK)
    newmsg1 = treatMSG(msg)
    rand1 = random.randint(1, q)  # r
    CH = ChameleonHash(PK, g, newmsg1, rand1)
    return {"CH": str(CH), "rand": str(rand1), "PK":str(PK)}

if __name__ == "__main__":

    SK = 48410017351108122866

    msg1 = 'woshidiyunlong'  # 消息m1
    msg2 = 'second message'  # 消息m2
    result = CH(msg1 ,SK)
    print(result) # int(result['rand']) 就是r1
    print(CHhashAPI(msg1, msg2, SK, int(result['rand'])))

水印 水印 水印 水印

有帮助的给小弟点个赞,给你比个💗💗哟

  • 12
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不染心

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值