当前位置: 首页 > article >正文

攻防世界GFSJ1193 cat_theory

题目编号:GFSJ1193

附件下载后是一个jpg文件和一个sage文件(python):

1. 分析图片(.jpg文件)

这个交换图展示的是一个加密系统的 同态加密 性质,其核心思想是:加密前的操作与加密后的操作具有某种兼容性。

图中符号解释

  1. M\mathcal{M}M 表示明文空间,即未加密的数据集合。
  2. C\mathcal{C}C 表示密文空间,即加密后的数据集合。
  3. Epk(⋅)E_{pk}(\cdot)Epk​(⋅) 表示加密算法,输入明文,输出密文,公钥为 pkpkpk。
  4. 箭头上的符号:
    • +++:表示在明文空间上的加法操作。
    • ×\times×:表示在密文空间上的乘法操作。

图的含义

上方路径(明文操作后加密)
  1. 从左上角开始,(m1,m2)∈M×M(m_1, m_2) \in \mathcal{M} \times \mathcal{M}(m1​,m2​)∈M×M,这是两个明文。
  2. 对这两个明文进行加法运算:m1+m2∈Mm_1 + m_2 \in \mathcal{M}m1​+m2​∈M。
  3. 将加法结果加密,得到密文:Epk(m1+m2)∈CE_{pk}(m_1 + m_2) \in \mathcal{C}Epk​(m1​+m2​)∈C。
下方路径(分别加密后在密文空间操作)
  1. 从左上角的明文对 (m1,m2)(m_1, m_2)(m1​,m2​),分别对 m1m_1m1​ 和 m2m_2m2​ 进行加密,得到密文对 (Epk(m1),Epk(m2))∈C×C(E_{pk}(m_1), E_{pk}(m_2)) \in \mathcal{C} \times \mathcal{C}(Epk​(m1​),Epk​(m2​))∈C×C。
  2. 在密文空间对这两个密文进行乘法操作:Epk(m1)×Epk(m2)∈CE_{pk}(m_1) \times E_{pk}(m_2) \in \mathcal{C}Epk​(m1​)×Epk​(m2​)∈C。
图的交换性质

      无论是 先对明文加法然后加密,还是 先分别加密然后对密文执行乘法,最终的结果都是相同的: Epk(m1+m2)=Epk(m1)×Epk(m2)E_{pk}(m_1 + m_2) = E_{pk}(m_1) \times E_{pk}(m_2)Epk​(m1​+m2​)=Epk​(m1​)×Epk​(m2​)

2. 分析代码(.sage文件),已添加详细注释

# 引入必要的库函数
from Crypto.Util.number import bytes_to_long, getStrongPrime, getRandomRange, getRandomNBitInteger
from secret import flag  # 导入flag(秘密信息)

class CatCrypto():
    """
    CatCrypto 类定义了一个加密系统,包括生成密钥对、加密和解密的实现。
    """

    def get_p_q(self) -> tuple:
        """
        生成符合要求的两个质数 p 和 q。
        p 是一个布卢姆质数(满足 p ≡ 3 (mod 4))。
        q 满足 gcd(p-1, q-1) = 2 的约束。
        """
        def get_blum_prime():
            """
            生成一个布卢姆质数。
            """
            while True:
                # 随机生成一个强质数,位数为 nbits 的一半
                p = getStrongPrime(self.nbits // 2)
                # 检查是否为布卢姆质数(p ≡ 3 (mod 4))
                if p % 4 == 3:
                    return p

        p = get_blum_prime()  # 生成第一个布卢姆质数 p
        q = 2  # 初始化 q 为 2(用于后续循环生成)
        # 确保 gcd(p-1, q-1) = 2
        while gcd(p-1, q-1) != 2:
            q = get_blum_prime()
            
        return p, q  # 返回生成的 p 和 q
    
    # 密钥生成器(KeyGen)
    def __init__(self, nbits=1024):
        """
        初始化 CatCrypto 实例,并生成加密系统的密钥。
        """
        self.nbits = nbits  # 设置密钥位数
        self.p, self.q = self.get_p_q()  # 生成质数 p 和 q
        p, q = self.p, self.q

        # 模数 n = p * q
        self.n = p * q
        n = self.n

        # λ = (p-1) * (q-1) // 2,是拉姆达函数的一种形式
        self.lam = (p-1) * (q-1) // 2

        # g 是 n + 1,这是一个特殊的选择
        self.g = self.n + 1

        # 生成随机数 x 并计算 h
        x = getRandomRange(1, n)  # 从 1 到 n-1 中随机选择 x
        h = -x^2  # 计算 h 为 -x^2
        # 计算 hs = h^n mod n^2
        self.hs = int(pow(h, n, n^2))

    # 加密(Enc)
    def enc(self, m: int) -> int:
        """
        加密一个明文整数 m。
        """
        n = self.n  # 模数 n
        hs = self.hs  # hs 是密钥中的一个参数
        
        # 随机选择一个 a,位数为 n 位的一半
        a = getRandomNBitInteger(ceil(n.bit_length() / 2))
        # 计算密文 c = (1 + m*n) * hs^a mod n^2
        c = (1 + m * n) * pow(hs, a, n^2)
        return int(c)  # 返回加密后的密文
        
    # 解密(Dec)
    def dec(self, c: int) -> int:
        """
        解密一个密文整数 c。
        """
        lam = self.lam  # 拉姆达值
        n = self.n  # 模数 n
        
        # 定义 L 函数:L(x) = (x-1) // n
        L = lambda x: (x - 1) // n
        
        # 计算模逆 mu = lam^-1 mod n
        mu = inverse_mod(lam, n)
        # 使用解密公式计算明文 m
        m = L(int(pow(c, lam, n^2))) * mu % n
        return m  # 返回解密后的明文
        
    # 定义 nbits 的属性方法(getter 和 setter)
    @property
    def nbits(self):
        return self.__nbits
    
    @nbits.setter
    def nbits(self, nbits):
        self.__nbits = nbits

# 初始化加密系统
cat = CatCrypto(nbits=1024)

# 将 flag 转换为整数 m
m = bytes_to_long(flag)
# 确保 m 的位数小于 1024 位
assert m.bit_length() < 1024

# 随机生成三个部分 m1, m2, m3,使得 m = m1 + m2 + m3
m1 = getRandomNBitInteger(m.bit_length() - 1)
m2 = getRandomNBitInteger(m.bit_length() - 2)
m3 = m - m1 - m2

# 加密三个部分
c1 = cat.enc(m1)
c2 = cat.enc(m2)
c3 = cat.enc(m3)

# 测试加密和解密结果
print(f'dec(c1*c2) = {cat.dec(c1*c2)}')
print(f'dec(c2*c3) = {cat.dec(c2*c3)}')
print(f'dec(c3*c1) = {cat.dec(c3*c1)}')

"""
dec(c1*c2) = 127944711034541246075233071021313730868540484520031868999992890340295169126051051162110
dec(c2*c3) = 63052655568318504263890690011897854119750959265293397753485911143830537816733719293484
dec(c3*c1) = 70799336441419314836992058855562202282043225138455808154518156432965089076630602398416
"""

3. 解题算法

问题分解

1. 我们有三个加密后的解密结果:
    
    - m1+m2
    - m2+m3
    - m3+m1
2. 目标是通过这些和值恢复原始值 m1,m2,m3 的总和 m=m1+m2+m3。
    
3. 数学上,这三个和值的总和为:
    
    (m1+m2)+(m2+m3)+(m3+m1)=2×(m1+m2+m3)
4. 换句话说:
    
    m1+m2+m3=[(m1+m2)+(m2+m3)+(m3+m1)]/2

计算的逻辑

通过提供的三个解密结果:

- m1+m2=127944711034541246075233071021313730868540484520031868999992890340295169126051051162110
- m2+m3=63052655568318504263890690011897854119750959265293397753485911143830537816733719293484
- m3+m1=70799336441419314836992058855562202282043225138455808154518156432965089076630602398416

将它们代入公式:

m=[(m1+m2)+(m2+m3)+(m3+m1)]/2

计算得:

m=127944711034541246075233071021313730868540484520031868999992890340295169126051051162110+63052655568318504263890690011897854119750959265293397753485911143830537816733719293484+707993364414193148369920588555622022820432251384558081545181564329650890766306023984162

结果即为明文 m1+m2+m3,而原始明文 flag 即是 m1+m2+m3的字节形式。

4. 算法实现

from Crypto.Util.number import long_to_bytes

m1_plus_m2 = 127944711034541246075233071021313730868540484520031868999992890340295169126051051162110
m2_plus_m3 = 63052655568318504263890690011897854119750959265293397753485911143830537816733719293484
m3_plus_m1 = 70799336441419314836992058855562202282043225138455808154518156432965089076630602398416

m = (m1_plus_m2 + m2_plus_m3 + m3_plus_m1) // 2
print(long_to_bytes(m))


http://www.kler.cn/a/416090.html

相关文章:

  • 【链表】【删除节点】【刷题笔记】【灵神题单】
  • 02_Django路由Router
  • 列表上移下移功能实现
  • 开发一套ERP 第七弹 RUst 操作数据库
  • 命令行使用ssh隧道连接远程mysql
  • 分布式搜索引擎之elasticsearch单机部署与测试
  • 使用 Docker Compose 来编排部署LMTNR项目
  • 图数据库 | 10、图数据库架构设计——高性能图存储架构(上)
  • Zookeeper实现分布式锁、Zookeeper实现配置中心
  • 使用Ansible进行Red Hat Linux自动化运维
  • 基于 SpringBoot 的夕阳红公寓管理系统资源整合与高效利用
  • Python 3 教程第33篇(MySQL - mysql-connector 驱动)
  • 长短期记忆网络 (LSTM) 简介
  • 基于Java Springboot蛋糕商城
  • 开源测试_log4net
  • C语言数据结构——详细讲解《队列》
  • uniapp App端在renderjs层渲染echarts获取不到service层id的问题
  • 数字化转型背景下,高职院校计算机网络应用的革新策略
  • C++算法练习-day49——108.将有序数组转换为二叉搜索树
  • 【人工智能基础】计算机视觉
  • ElementUI:el-drawer实现在父组件区域内打开抽屉组件非全屏
  • git如何创建一次没有修改的commit
  • windows C#-取消任务列表(下)
  • python画图plt.close()一直闪烁
  • webpack5提升打包构建速度(四)
  • 详解 YOLOv5 模型运行参数含义以及设置及在 PyCharm 中的配置方法