攻防世界GFSJ1229 Three

news/2024/11/6 5:05:02 标签: python, 开发语言, 网络安全, CTF

题目编号:GFSJ1229

解题过程

1. 附件下载是三个压缩包A.zip B.zip C.zip和一个python程序Three.py


2. A.zip可以直接解压出来,内容如下:

```
'2022-08-27 20:16:04.246131' Func A0*X0+B0
'2022-08-27 20:16:05.116859' Read_Data A0.txt->A0(28829613228241459)
'2022-08-27 20:16:06.097964' Secret_Share A0
'2022-08-27 20:16:07.022455' Get A00(200254991086689) A01(200241552690281)
'2022-08-27 20:16:07.925862' Get X00(200058430391504) X01(200401773940794)
'2022-08-27 20:16:09.077771' Mul_loc_compute A0,X0->C00
'2022-08-27 20:16:10.764928' RGet C02(924422050091355025836012334663090)
'2022-08-27 20:16:11.213530' ReShare C00(random mask is 507412160912)
'2022-08-27 20:16:12.153062' Get B00(199957680670222) B01(200362172648094)
'2022-08-27 20:16:13.100727' Add_loc_compute C00,B00->Y00
'2022-08-27 20:16:13.281906' ReShare Y00(random mask is -1008362525723)
'2022-08-27 20:16:14.017485' RGet Y02(924422050091362838179268571917871)
'2022-08-27 20:16:17.000001' Open Y00
'2022-08-27 20:16:17.000101' RGet Y01(12163251699969281466186532960410)
'2022-08-27 20:16:17.000299' Cyberloafing!!
'2022-08-27 20:16:17.004194' ReBuild Y0
'2022-08-27 20:16:17.013270' Save_Data

```
3. B.zip 和C.zip有密码,查看Three.py,代码加了注释后如下:


```Python
import datetime

import numpy as np

  

# 协议类,用于处理多方参与的加密计算

class Protocol:

def __init__(self, party_num):

# 初始化协议类,指定当前参与方编号 (party_num: 0, 1, 或 2)

self.pn = party_num # 参与方编号 (party_num: 0, 1, 2)

  

def Read_Data(self, path):

# 读取数据文件中的内容,尝试将其转换为数值(整数或浮点数)

data = open(path).readline().strip() # 从文件中读取一行数据并去除首尾空格

try:

if '.' in data:

data = float(data) # 如果数据包含小数点,则转换为浮点数

else:

data = int(data) # 否则,转换为整数

except:

# 如果转换失败,打印错误信息并退出程序

print('No number')

exit(-1)

return data # 返回读取的数据

  

def Get(self, x1, x2):

# 获取两个秘密共享的值 (函数未实现)

pass

  

def RGet(self, x1):

# 获取一个秘密共享的值 (函数未实现)

pass

  

def ReShare(self, x):

# 重新共享值 x,x = x + ri,其中 r0 + r1 + r2 = 0

# ri (i=0,1,2) 是随机整数,然后将 x 发送给 (self.pn + 1) % 3 的参与方

pass

  

def Secret_Share(self, x):

# 秘密共享函数,将 x 拆分为三个秘密共享的值

# x1 和 x2 是随机整数,x3 = x - x1 - x2

# sharelist 存储了三部分的秘密共享值,loc 确定了当前参与方的位置

# reserved 保存了两个与当前参与方相关的共享值,用于后续计算

x1, x2 = np.random.randint(0, 100), np.random.randint(0, 100) # 随机生成 x1 和 x2

x3 = x - x1 - x2 # 计算 x3,使 x1 + x2 + x3 = x

sharelist = [x1, x2, x3] # 将 x 分成三个部分

loc = self.pn # 当前参与方的位置

self.reserved = (sharelist[loc], sharelist[(loc + 1) % 3]) # 保留两个共享值

return (sharelist[0], sharelist[1]), (sharelist[1], sharelist[2]), (sharelist[2], sharelist[0])

  

def Mul_loc_compute(self, x1, y1, x2, y2):

# 局部乘法计算,使用秘密共享的 x1 和 y1 计算乘积

# 计算过程为 x1*y1 + x1*y2 + x2*y1,并将结果存储在 self.mulx

self.mulx = x1 * y1 + x1 * y2 + x2 * y1

  

def Add_loc_compute(self, x1, y1):

# 局部加法计算,计算两个共享值的和并存储在 self.addx

self.addx = x1 + y1

  

def Cyberslacking(self):

# 打印表示 "消极工作" 的消息 (仅作示例用途)

print('Cyberloafing!!')

print('Cyberloafing!!')

print('Cyberloafing!!')

  

def Save_Data(self):

# 保存数据的默认方法 (可选)

# 使用当前时间生成密码 (pwd),压缩所有数据后重建函数的答案 (未实现)

pwd = str(datetime.datetime.now())

pass

  

def Func(self, expression):

# 打印数学表达式,将会计算表达式,但保证隐私不泄露

print('Math expression', expression, 'will be computed! You can get the answer without leak your privacy!')

  

def ReBuild(self, x1, x2, x3):

# 重建函数的答案,利用秘密共享的值 x1, x2, x3 求和得到原始数据

return x1 + x2 + x3

  

# 示例:A0 表示 'flag{xxxxxxxxxxx',X0 表示 xxxxx...xxx,B0 表示 xxxxxxxxx}

# A (参与方 0) 拥有 A0,B (参与方 1) 拥有 X0,C (参与方 2) 拥有 B0

# 函数表示 A0 * X0 + B0

p0 = Protocol(0)

p1 = Protocol(1)

p2 = Protocol(2)
```
是C的算法,其中pwd = str(datetime.datetime.now())暴露了如何计算密码的,密码格式为当前时间精确到微秒,如'YYYY-MM-DD HH:MM:SS.ssssss'。

4. 破解C.zip的密码:


```python
## Three.py是C的算法

  

import zipfile # 导入 zipfile 库,用于处理 ZIP 文件

  

def extract(file, password):

"""

解压指定的 ZIP 文件到当前目录,使用给定的密码解压缩。

参数:

- file: 要解压缩的 zipfile.ZipFile 对象

- password: 解压密码,以字符串列表的形式提供

"""

file.extractall(path='.', pwd=''.join(password).encode('utf-8')) # 将密码拼接为字符串并编码为 UTF-8 格式

  

# 初始化空的密码列表,将用于存储所有可能的密码组合

password_lst = []

# 设置密码前缀,假设所有密码以同一时间戳前缀开头

prestr = '2022-08-27 20:16:17.'#从A.txt中找到getData的起始时间

  

# 构造 6 位数的密码组合并添加到 password_lst 列表中

for i in range(0, 999999): # 生成从 000000 到 999999 的所有可能组合

s = str(i) # 将数字转换为字符串

tmpnum = '0' * (6 - len(s)) + s # 前面补足 0 使其成为 6 位数

password_lst.append(prestr + tmpnum) # 将时间戳前缀和 6 位数字组合并添加到密码列表

  

# 打开指定路径的 ZIP 文件,并设为读模式

zfile = zipfile.ZipFile("C.zip", 'r')

  

# 遍历所有可能的密码,尝试解压 ZIP 文件

for pwd in password_lst:

try:

extract(zfile, pwd) # 尝试使用当前密码解压缩

print(pwd) # 如果解压成功,打印正确的密码

break # 成功后退出循环

except:

continue # 如果解压失败(密码错误),继续尝试下一个密码

  

##print: 2022-08-27 20:16:17.930813
```

5. 使用上面获得的密码解压C.zip, 获得C.txt内容如下:


```
'2022-08-27 20:16:04.911132' Func A0*X0+B0
'2022-08-27 20:16:07.201341' Get A02 A00
'2022-08-27 20:16:07.800077' Get X02 X00
'2022-08-27 20:16:08.303948' Mul_loc_compute A0,X0->C02
'2022-08-27 20:16:10.662982' ReShare C02
'2022-08-27 20:16:10.872634' RGet C01
'2022-08-27 20:16:11.412399' Read_Data B0.txt->B0
'2022-08-27 20:16:11.729341' Secret_Share B0
'2022-08-27 20:16:11.800012' Get B02 B00
'2022-08-27 20:16:12.214092' Add_loc_compute C02,B02->Y02
'2022-08-27 20:16:13.334908' ReShare Y02(random mask is 507036073644)
'2022-08-27 20:16:13.923122' RGet Y01
'2022-08-27 20:16:15.000382' Open Y02
'2022-08-27 20:16:17.000892' RGet Y00
'2022-08-27 20:16:17.009702' Cyberloafing!!
'2022-08-27 20:16:17.019991' ReBuild Y0
'2022-08-27 20:16:17.930813' Save_Data
```

6. A.txt和C.txt提供了A0、A1以及加密分享和掩码,以及过程中的Y0和X0相关值,可以逆向计算,因为总的计算公式是A0*X0+B0=Y0,可以求出B0,计算程序如下:


```python
from Crypto.Util.number import long_to_bytes

  

# 定义局部乘法计算函数

# 通过已知的秘密共享值 A00、A01、X00 和 X01,计算出 C00 的真实值

# 此函数在秘密共享中用于计算多方参与的局部乘法

def Mul_loc_compute(x1, y1, x2, y2):

return x1 * y1 + x1 * y2 + x2 * y1

  

# 已知的 A0 值和各秘密共享的具体值,根据日志记录得出以下共享值:

# A0:是目标值,日志显示为 28829613228241459。

# A00_true 和 A01_true 是 A0 的两个共享值,来自 A 方日志的 'Get A00' 和 'Get A01'。

# X00_true 和 X01_true 是 X0 的两个共享值,来自 A 方日志的 'Get X00' 和 'Get X01'。

A0 = 28829613228241459

A00_true = 200254991086689

A01_true = 200241552690281

X00_true = 200058430391504

X01_true = 200401773940794

B00_true = 199957680670222

  

# 计算 C00 的真实值

# 使用 Mul_loc_compute 函数来计算局部乘法结果 C00_true,以便后续计算。

# 通过 A00_true 和 X00_true, A01_true 和 X01_true 的共享值计算得出。

C00_true = Mul_loc_compute(A00_true, X00_true, A01_true, X01_true)

  

# 根据日志,C00 经过了掩码操作,掩码值为 507412160912,来源于 A 方日志的 'ReShare C00'。

# 计算带掩码的 C00 值(C00_mask),供后续 Y00 的计算使用。

C00_mask = C00_true + 507412160912

  

# 计算 Y00_true

# 根据 A 方日志的 'Add_loc_compute C00,B00->Y00' 可知 Y00 是 C00 和 B00 的局部相加结果

# 因此,Y00_true = C00_mask + B00_true。

Y00_true = C00_mask + B00_true

  

# A 方日志的 'ReShare Y00' 显示 Y00 被应用了掩码 -1008362525723

# 计算出 Y00 的带掩码值 Y00_mask,以供最终计算使用。

Y00_mask = Y00_true + (-1008362525723)

  

# 读取 C 方日志获取 Y02 的带掩码值 924422050091362838179268571917871 和掩码 507036073644

# Y02_mask 和 Y02_true 分别表示 Y02 的带掩码值和真实值

Y02_mask = 924422050091362838179268571917871

Y02_true = Y02_mask - 507036073644

  

# C 方日志显示 Y01_mask 值为 12163251699969281466186532960410,将其直接使用

Y01_mask = 12163251699969281466186532960410

  

# A 方日志显示 C02_mask 的值为 924422050091355025836012334663090

# 使用 Y02_true 和 C02_mask 计算 B02_true,这是 B0 的一部分。

C02_mask = 924422050091355025836012334663090

B02_true = Y02_true - C02_mask

  

# 根据 A 和 C 日志中 B 的各共享值 (B00_true, B01_true) 以及计算出的 B02_true

# 还原 B0 值,这是最终的关键结果之一。

B01_true = 200362172648094

B0 = B00_true + B01_true + B02_true

  

# 计算 Y0 的总和,用于还原 X0 值

# 使用 Y00_mask、Y01_mask 和 Y02_mask,通过累加得到 Y0 的值

Y0 = Y00_mask + Y01_mask + Y02_mask

  

# 计算 X0 值

# 根据公式 X0 = (Y0 - B0) // A0 计算得出 X0,这是最终需要的另一个关键结果

X0 = (Y0 - B0) // A0

  

# 将 A0、X0 和 B0 转换为 ASCII,并组合成 flag,代表最终解密的结果。

flag = long_to_bytes(A0) + long_to_bytes(X0) + long_to_bytes(B0)

print(flag)# b'flag{23snyau_sllpmxcz}'
```


7. 备注解释下多方加密(by AI)


在这个三方安全计算协议中,`A00`、`B00`、`C00`、`X00` 等变量是每个参与方持有的秘密共享值的部分。这些共享值通过分割和掩码等方式隐藏了原始数据,在不泄露完整信息的情况下进行计算。

### 各变量的含义

- **A0、B0、X0**:这些是原始值,代表 Allen、Bob 和其他参与方各自拥有的秘密数据。例如:
  - `A0`:由 Allen 持有的原始值。
  - `X0`:是 Allen 和其他参与方希望参与计算的一个值。
  - `B0`:由 Bob 持有的原始值。

- **A00、B00、C00、X00**:这些是 `A0`、`B0`、`C0`、`X0` 的分片,每个原始值被分割为多份秘密共享的片段,各参与方只持有其中一部分。
  - **A00**:`A0` 的分片,由参与方之一持有。
  - **B00**:`B0` 的分片,由参与方之一持有。
  - **C00**:`C0` 的分片,这是计算过程中生成的中间结果。
  - **X00**:`X0` 的分片。

这些分片和共享值的划分是为了让多个参与方共同进行计算,同时保护隐私,使得单个参与方无法独立得出完整的原始数据。

### 计算流程概述

在一次多方计算中,每个参与方通过持有的共享值分片参与运算,具体的流程如下:

1. **秘密共享(Secret Sharing)**:
   - 将每个参与方的原始值(如 `A0`、`B0`、`X0`)分成多个共享片段,如 `A00`、`A01`、`A02` 等。
   - 这些共享片段被分配给不同的参与方。例如,Allen 可能持有 `A00`,Bob 持有 `A01`,Crosley 持有 `A02`。这样,任何单独一个片段都无法还原 `A0` 的完整值。

2. **局部计算(Local Computation)**:
   - 每个参与方在自己持有的分片上执行局部计算。例如:
     - Allen 计算 `A00 * X00`,Bob 计算 `A01 * X01`,Crosley 计算 `A02 * X02`。
   - 这些局部计算结果形成了 `C00`、`C01`、`C02` 等中间共享值。

3. **重新共享和掩码处理(ReShare and Masking)**:
   - 为了防止泄露中间结果,每个参与方会给自己的计算结果加上随机掩码。例如,Allen 的局部计算结果 `C00` 会加上一个掩码 `C00_mask`。
   - 然后,带掩码的结果 `C00_mask` 会被共享给其他参与方,以供后续的合并计算。

4. **合并局部结果(Combine Local Results)**:
   - 所有局部计算的结果(如 `C00_mask`, `C01_mask`, `C02_mask`)在各参与方间汇总,通过计算得到最终结果的共享值。
   - 合并结果的过程确保了各参与方能共同计算出所需的结果(例如 `A0 * X0 + B0`),而每个参与方都不会泄露自己的原始数据。

5. **最终重建(ReBuild)**:
   - 当所有计算完成后,所有共享值可以重构为最终结果。各方将合并后的共享值返回给 Allen,Allen 可以使用这些值恢复出最终的结果。

### 例子:如何运作

假设 Allen 希望计算 `A0 * X0 + B0`,整个过程可以总结如下:

1. **秘密共享阶段**:`A0`、`X0` 和 `B0` 被分割成 `A00, A01, A02`,`X00, X01, X02`,`B00, B01, B02` 三个部分,每个参与方持有一部分。
2. **局部计算**:每个参与方计算 `A00 * X00`、`A01 * X01`、`A02 * X02`。
3. **掩码和重新共享**:每个局部结果加上随机掩码,形成 `C00_mask`、`C01_mask`、`C02_mask`,防止泄露中间数据。
4. **加法和最终重建**:各方汇总带掩码的局部结果,并执行加法操作得到加法结果 `Y0`。最终 `Y0` 被重构并解码,恢复出最终的计算结果。

通过这种流程,所有参与方可以在保护数据隐私的同时共同完成 `A0 * X0 + B0` 的计算。


http://www.niftyadmin.cn/n/5740202.html

相关文章

物理验证Calibre LVS Debug案例之通过deleteEmptyModule解决LVS问题

上周帮助T12nm A55训练营学员debug一个Calibre LVS问题,小编觉得挺好的一个问题。这个问题之前没有遇到过,今天分享给大家。 数字IC后端先进工艺设计实现之TSMC 12nm 6Track工艺数字IC后端实现重点难点盘点 下图所示为Calibre LVS的报告。从报告中看到…

苍穹外卖day-01

后端环境搭建 创建git仓库 提交代码 创建gitee远程仓库 开始连接远程仓库 运行sql文件,创建数据库。这里选取的可视化工具是navicat 编译一下项目 运行项目 登录的账号和密码在数据库中的emploee表中 退出前端界面登录后再重新登录,可以从后台清晰看到前…

Ubuntu22.04在Docker下安装Mysql5.7

Ubuntu22.04在Docker下安装Mysql5.7 通常在项目研发阶段为了开发测试方便此处mysql安装在docker下(便于移至和扩展比较灵活),必须要注意在生产环境中不推荐直接安装在docker下 打开官网地址:https://hub.docker.com/&#xff08…

asp.net网站项目如何设置定时器,定时获取数据

在 Global.asax.cs 文件中编写代码来初始化和启动定时器。Global.asax.cs 文件定义了应用程序全局事件,比如应用程序的启动和结束。在这里,我们将在应用程序启动时初始化和启动定时器。 using System; using System.Timers;public class Global : Syste…

(C++回溯算法)微信小程序“开局托儿所”游戏

问题描述 给定一个矩阵 A ( a i j ) m n \bm A(a_{ij})_{m\times n} A(aij​)mn​,其中 a i j ∈ { 1 , 2 , ⋯ , 9 } a_{ij}\in\{1,2,\cdots,9\} aij​∈{1,2,⋯,9},且满足 ∑ i 1 m ∑ j 1 n a i j \sum\limits_{i1}^m\sum\limits_{j1}^na_{ij} i…

web开发Django+vue3

返回验证码图片 后端:返回Http对象,content_type设置为image # 验证码测试视图函数 def get_captcha(request):img, code generate_captcha() # 生成验证码request.session[captcha_code] code # 将验证码保存到session中buf BytesIO() # 创建一…

[spark面试]spark与mapreduce的区别---在DAG方面

1、spark中的task是以线程实现的,而mapreduce中是以进程实现的。 进程的频繁启动和停止会增加资源的消耗。 2、spark中支持DAG,而mapreduce不支持DAG DAG的使用:为什么支持DAG会更加高效 1)、在DAG图中,会将一个job…

Linux 服务器使用指南:从入门到登录

🌟快来参与讨论💬,点赞👍、收藏⭐、分享📤,共创活力社区。 🌟 🚩博主致力于用通俗易懂且不失专业性的文字,讲解计算机领域那些看似枯燥的知识点🚩 目录 一…