变色龙哈希代码实现(不用导入pyunit_prime库,直接进行函数实现)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

代码

因为现在pyunit_prime库很难通过pip下载,而在网上找的教程自己手动下载又出现各种bug,于是直接编写了函数代码进行功能的实现。

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

p = 0
q = 0


def is_prime(n: int, k: int = 5) -> bool:
    """
    使用Miller-Rabin素性检验算法判断一个数n是否可能是素数。
    参数:
        n (int): 待检验的正整数
        k (int): 重复检验次数,默认为5,以保证错误率极低
    返回:
        bool: 如果n可能是素数,返回True;否则返回False
    """
    if n <= 1 or (n % 2 == 0 and n != 2):
        return False
    if n <= 3:  # 新增条件判断,避免n - 2小于等于1
        return True
    def witness(a: int) -> bool:
        d = n - 1
        s = 0
        while d % 2 == 0:
            d //= 2
            s += 1

        x = pow(a, d, n)
        if x == 1 or x == n - 1:
            return False

        for _ in range(s - 1):
            x = pow(x, 2, n)
            if x == n - 1:
                return False

        return True

    for _ in range(k):
        a = random.randint(2, n - 2)
        if witness(a):
            return False

    return True

def get_large_prime_length(length: int) -> int:
    """
    生成一个指定二进制长度的大素数。
    参数:
        length (int): 素数期望的二进制位数
    返回:
        int: 找到的大素数
    """
    def is_sufficiently_large_prime(num: int) -> bool:
        return num > (1 << length - 1) and is_prime(num)

    lower_bound = 1 << length
    upper_bound = (1 << length) + (1 << (length - 1))  # 增加一半长度以提高找到素数的概率

    while True:
        candidate = random.randint(lower_bound, upper_bound)
        if is_sufficiently_large_prime(candidate):
            return candidate

def prime_range(start: int, end: int) -> List[int]:
    """
    生成指定范围内所有素数的列表。
    参数:
        start (int): 范围起始值(含)
        end (int): 范围结束值(不含)
    返回:
        List[int]: 范围内的素数列表
    """
    primes = []
    for num in range(start, end):
        if is_prime(num):
            primes.append(num)
    return primes
def primeFactorization(length):  # 分解质因数
    global p, q
    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


def quickPower(a, b, 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):  # 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 getSecretKey():  # get SK,x
    x = random.randint(1, q)
    return x


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


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


if __name__ == "__main__":
    print('calculating...')
    print('')
    length = 100  # 随机大素数长度
    result = primeFactorization(length)
    g = getGenerator(result)
    SK = getSecretKey()
    PK = getPublicKey(g, SK)

    msg1 = 'i sent first message'  # 消息1
    msg2 = 'second message'  # 消息2
    newmsg1 = treatMSG(msg1)
    newmsg2 = treatMSG(msg2)
    rand1 = random.randint(1, q)  # r

    print('q=', q)
    print('p=', p)
    print('g=', g)
    print('SK=', SK)
    print('PK=', PK)
    print('')

    print('msg1=', msg1)
    print('rand1=', rand1)
    CH = ChameleonHash(PK, g, newmsg1, rand1)
    print('CH=', CH)

    print('-----------------')
    print("使用Forge函数伪造第msg2的随机数rand2,以使得两个变色龙哈希相等")

    print('msg2=', msg2)
    rand2 = Forge(SK, newmsg1, rand1, newmsg2)
    print('rand2=', rand2)
    newCH = ChameleonHash(PK, g, newmsg2, rand2)
    print('newCH=', newCH)

    print("程序演示了如何利用变色龙哈希的特性,即对于同一公钥和生成元,不同的消息可以有相同的哈希值,前提是知道消息之间的关系和私钥。")

总结

将上述代码运行即可得到演示结果。
代码借鉴:https://github.com/Zipzapztc/ChameleonHash/blob/master/ChameleonHash.py

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值