复杂和简单矛盾的加密题——江苏省第四届数据安全技术应用职业技能竞赛初赛"

admin 2026-10-20 07:48:53 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

cover_image

复杂和简单矛盾的加密题——江苏省第四届数据安全技术应用职业技能竞赛初赛

原创

一只岸上的鱼
一只岸上的鱼

一只岸上的鱼

2026年7月10日 08:33
江苏

在小说阅读器读本章

去阅读

复杂和简单矛盾的加密题——江苏省第四届数据安全技术应用职业技能竞赛初赛

缘起

对于RSA加密题,我一直认为自己只能做一个脚本小子————收集每一次遇到的新题型,只希望下次比赛用得上

针对新出现的,稍微修改一点逻辑,需要根据一下新的加密算法或者推导逻辑去修改的,我都只能放弃了

但是自动AI的出现,一切都变了:

如果允许使用AI,那么这些题目就像签到题一样,虽然扔给一个大模型,基本都能解,毕竟只是一道数学题而已

如果不允许使用AI,那还是不要浪费时间,在其他题目上花点时间吧/(ㄒoㄒ)/~~

今天这题,也是没做出来了,赛后扔个ai,分分钟给了答案,这里只记录一下环境的搭建:

需要sagemath的运行环境

题目:

题干很简单,但是附件代码却基本看不懂/(ㄒoㄒ)/~~

题目附件内容我都放在了cnb:https://cnb.cool/netvvorm/items/datasecurity26

解题

解题没什么好说了,就是将附件代码和题干,全发给了大模型,没过几分钟,吐给我一个代码:

python

# CGL Hash Inversion - Complete SageMath Solution
#
# This script should be run in SageMath (not plain Python).
# It correctly implements BFS on the 2-isogeny graph to find the path.

PRIME = (2**13) * (3**7) - 1
print(f\"PRIME = {PRIME}\")

# Setup the field and curve
K.<i> = GF(PRIME**2, modulus=x**2 + 1)
Y = polygen(K)

E0 = EllipticCurve(K, [0, 6, 0, 1, 0])
start_j = E0.j_invariant()
print(f\"start_j = {start_j}\")

# Classical modular polynomial of level 2
Phi2 = classical_modular_polynomial(2).change_ring(K)
vars2 = Phi2.parent().gens()

# CGL hash function (forward)
def CGL_hash(msg_bits, j_start):
    curr_j = j_start
    prev_j = None
    for bit in msg_bits:
        f = Phi2.subs({vars2[0]: curr_j, vars2[1]: Y})
        if hasattr(f, 'univariate_polynomial'):
            f = f.univariate_polynomial()
        roots = f.roots(multiplicities=False)
        valid_neighbors = [r for r in roots if r != prev_j]
        valid_sorted = sorted(valid_neighbors, key=lambda r: [int(c) for c in r.list()])
        prev_j = curr_j
        curr_j = valid_sorted[bit]
    return curr_j

# Get neighbors function
def get_neighbors(j):
    f = Phi2.subs({vars2[0]: j, vars2[1]: Y})
    if hasattr(f, 'univariate_polynomial'):
        f = f.univariate_polynomial()
    return f.roots(multiplicities=False)

# BFS to find path from start_j to target_j
def BFS_find_path(start_j, target_j, max_depth=100):
    from collections import deque

    queue = deque()
    queue.append((start_j, None, []))  # (curr_j, prev_j, path)
    visited = set()
    visited.add((start_j, None))

    nodes_explored = 0

    while queue:
        curr_j, prev_j, path = queue.popleft()
        nodes_explored += 1

        if nodes_explored % 10000 == 0:
            print(f\"  Explored {nodes_explored} nodes, depth {len(path)}\")

        if len(path) > max_depth:
            continue

        neighbors = get_neighbors(curr_j)
        valid = [r for r in neighbors if r != prev_j]
        if prev_j is None:
            valid = neighbors  # At first step, all 3 neighbors are valid (bits 0 and 1 use first 2)

        valid_sorted = sorted(valid, key=lambda r: [int(c) for c in r.list()])

        for bit_idx in range(min(2, len(valid_sorted))):
            next_j = valid_sorted[bit_idx]
            new_path = path + [bit_idx]

            if next_j == target_j:
                return new_path

            state = (next_j, curr_j)
            if state not in visited:
                visited.add(state)
                queue.append((next_j, curr_j, new_path))

    print(f\"Explored {nodes_explored} nodes, target not found.\")
    return None

# Target j-invariant from the problem
target_j = K(17702267 + 9824216*i)
print(f\"target_j = {target_j}\")

# Run BFS
print(\"\
Running BFS to find path...\")
path = BFS_find_path(start_j, target_j, max_depth=80)

if path is None:
    print(\"Path not found within depth limit.\")
else:
    print(f\"\
Found path: {path}\")
    print(f\"Path length: {len(path)}\")

    # Verify
    computed = CGL_hash(path, start_j)
    print(f\"Computed target: {computed}\")
    print(f\"Expected target: {target_j}\")

    if computed == target_j:
        print(\"\
✓ Path verified! Now decrypting...\")

        # Decrypt
        from Crypto.Cipher import AES
        from Crypto.Util.Padding import unpad
        import hashlib

        secret_path_str = str(path)
        print(f\"Secret path string: {secret_path_str}\")
        aes_key = hashlib.sha256(secret_path_str.encode()).digest()[:16]
        print(f\"AES key (hex): {aes_key.hex()}\")

        ct_hex = \"3cea38f9b42cb724edf17080682bf33f782f1a9652163a87001f0aab505ae39d86a808b0a7b817d83082ef7fdd3d195662d78c34aeda37e32f16f5303d352c12\"
        ct = bytes.fromhex(ct_hex)
        iv = ct[:16]
        cipher = AES.new(aes_key, AES.MODE_CBC, iv=iv)
        pt = unpad(cipher.decrypt(ct[16:]), 16)
        print(f\"\
*** FLAG: {pt.decode()} ***\")
    else:
        print(\"Path verification FAILED!\")

# If BFS doesn't find the path, try with larger depth or different strategy
print(\"\
Done.\")

是时候准备一个sagemath环境了

我还是在cnb制作了一个环境,基于官方的docker镜像:

https://cnb.cool/ikunkun/demo/sagepreview

启动后点开demo,就是这个题解:

小结

就目前来说,对于加密解密的代码题,还是蛮纠结的,想要入门,得花不少时间和精力,

如果可以用大模型,那这大部分时候就是一签到题,花费大量力气去学感觉又不值得,迷惘中……


复杂和简单矛盾的加密题——江苏省第四届数据安全技术应用职业技能竞赛初赛" 网络安全文章

复杂和简单矛盾的加密题——江苏省第四届数据安全技术应用职业技能竞赛初赛"

本文记录了江苏省第四届数据安全技术应用职业技能竞赛初赛中的一道RSA加密题解题过程。作者自认是脚本小子,但发现利用AI大模型可轻松解决此类数学题。文章详细描述了使用SageMath环境进行CGL哈希逆运算的BFS搜索,最终找到路径并解密获得FLAG。作者分享了环境搭建和完整解题代码,并对是否值得深入学习加密技术表达了迷惘。
中国企业出海,数据合规服务商哪家强?扬帆安全报告发布·附下载" 网络安全文章

中国企业出海,数据合规服务商哪家强?扬帆安全报告发布·附下载"

该报告系统梳理了中国企业出海数据合规服务生态,将服务商分为法律咨询、技术方案、认证等五大类别,并针对不同行业和发展阶段提供选型建议。报告强调数据合规已从锦上添花演变为全球化经营的基础能力,提醒企业警惕伪合规服务,注重属地化经验与技术能力。建议出海企业通过扬帆安全公众号获取完整报告以指导合规实践。
解读 Anthropic 的 AI Agent零信任框架" 网络安全文章

解读 Anthropic 的 AI Agent零信任框架"

Anthropic发布AIAgent零信任框架,指出AI智能体的非确定性本质打破了传统零信任假设。框架提出最小自主权原则,区分硬边界与软边界控制,强调爆炸半径控制与自动化响应。核心挑战在于漏洞利用时间窗口从数月压缩至数小时,要求组织在零信任基础上构建适应自主AI的隔离架构。
网安早报【20260710】164期" 网络安全文章

网安早报【20260710】164期"

2026年7月10日网安早报汇总了20条安全事件,包括西班牙逮捕网络犯罪同谋、伊朗黑客组织攻击医疗物流行业、Helix团伙利用语音钓鱼窃取数据、FBI就TeamPCP供应链攻击发警报、GodDamn勒索软件利用微软签名驱动攻击、多个漏洞披露如WolfSSL和RoundCube零点击漏洞、全球反欺诈行动逮捕5811人并拦截2.93亿美元资产等。关键发现是威胁多样化且攻击手法升级,建议加强供应链安全监控和MFA防护。
评论:0   参与:  0