2021-07-05

一、又是CRT([V&N2020 公开赛]CRT改)

题目

import hashlib
from functools import reduce
from Crypto.Util.number import *

ms = [getRandomNBitInteger(128) for i in range(8)]
p = reduce(lambda x,y: x*y, ms)#(ms内元素相乘)
x = getRandomRange(1, p)
cs = [x % m for m in ms]

flag = "flag{" + hashlib.sha256(str(x).encode()).hexdigest() + "}"
# assert("6db1ad4e" in flag)
print(flag)
# ms = [225171945994442247996581055098823263139, 310193846708532070976230730840060255113, 294717022803450326034461172866846896626, 323041742184244574340545985431264453307, 323134658040029031950091984536193316987, 198722498762116028361967364117672805554, 275420276991315547146652539118755199170, 220933201077147479374879093480591083540]
# cs = [50664790127162750730845109587767933015, 91745865104647958764847661520573459998, 88986425477751913267388500134576385858, 163483062360460301108125623316040949505, 120323223927022415995635580090556794061, 64307517531018530908505632173120904336, 7162453244593375550627134908252284080, 55840904472801221491492987502626897930]

解题思路

提示了CRT,那就用呗。
不过还有关键的一点是:若 a mod m1 = c1,a mod m2 = c2,用CRT解出来的a 0有:a = a0 + k* lcm(m1,m2).
综上,可以通过暴力循环k求出a。

解题脚本

import hashlib
from functools import reduce
from Crypto.Util.number import *
from gmpy2 import *
from sympy.ntheory.modular import *
ms = [225171945994442247996581055098823263139, 310193846708532070976230730840060255113, 294717022803450326034461172866846896626, 323041742184244574340545985431264453307, 323134658040029031950091984536193316987, 198722498762116028361967364117672805554, 275420276991315547146652539118755199170, 220933201077147479374879093480591083540]
cs = [50664790127162750730845109587767933015, 91745865104647958764847661520573459998, 88986425477751913267388500134576385858, 163483062360460301108125623316040949505, 120323223927022415995635580090556794061, 64307517531018530908505632173120904336, 7162453244593375550627134908252284080, 55840904472801221491492987502626897930]
p=25983568833051369099534720388911346955235148267605069778008905043552343837364191159733947367240762046537177181963818819600894769372449535976476936489671994061007537258715632820123146533166662374657012086170584043013302608395931139709515119140460978331094514035477807136559928558467975924981129185008480453600
#p=reduce(lambda x,y:x*y,ms)
x=crt(ms,cs)[0]
klcm=lcm(ms[0],ms[1])
for i in range(6):
    klcm=lcm(klcm,ms[i+2])
k=1
while True:
    flag = "flag{" + hashlib.sha256(str(x+k*klcm).encode()).hexdigest() + "}"
    if "6db1ad4e" in flag:
        print(x+k*klcm)
        print(flag)
        print(k)
        break
    k+=1

二、弗洛伊德(Floyd)

最短路径问题,要求1到26的最短路径
在这里插入图片描述
核心算法:

for k in range(n):
   for i in range(n):
       for j in range(n):
           if graph[i][k] + graph[k][j] < graph[i][j]:
               graph[i][j] = graph[i][k] + graph[k][j]
               parents[i][j] = parents[k][j]  # 更新父结点

网上扒拉了一下开脚本
解题脚本:

import sys
sys.setrecursionlimit(100000000)
# 弗洛伊德算法
def floyd():
    n = len(graph)
    for k in range(n):
        for i in range(n):
            for j in range(n):
                if graph[i][k] + graph[k][j] < graph[i][j]:
                    graph[i][j] = graph[i][k] + graph[k][j]
                    parents[i][j] = parents[k][j]  # 更新父结点

# 打印路径
def print_path(i, j):
    if i != j:
        print_path(i, parents[i][j])
    print(j+1, end='-->')

# Data [u, v, cost]
datas = [[1, 2, 100],[2, 3, 87],[2, 4, 57],[2, 5, 50],[2, 6, 51],[3, 7, 94],[3, 8, 78],[3, 9, 85],[4, 13, 54],[4, 14, 47],[4, 15, 98],[5, 10, 43],[5, 11, 32],[5, 12, 44],[6, 16, 59],[6, 17, 92],[6, 18, 39],[6, 23, 99],[7, 19, 99],[8, 20, 96],[9, 20, 86],[10, 21, 60],[11, 21, 57],[12, 22, 47],[14, 10, 55],[16, 17, 59],[18, 12, 53],[18, 24, 93],[21, 22, 33],[19, 25, 88],[20, 25, 96],[22, 25, 23],[25, 26, 75]]

n = 26

# 无穷大
inf = 9999999999

# 构图
graph = [[(lambda x: 0 if x[0] == x[1] else inf)([i, j]) for j in range(n)] for i in range(n)]
parents = [[i] * n for i in range(len(datas))]  # 关键地方,i-->j 的父结点初始化都为i
for u, v, c in datas:
    graph[u-1][v-1] = c	# 因为是有向图,边权只赋给graph[u][v]
    #graph[v][u] = c # 如果是无向图,要加上这条。

floyd()

print('Costs:')
for row in graph:
    for e in row:
        print('∞' if e == inf else e, end='\t')
    print()

print('\nPath:')
for i in range(n):
    for j in range(n):
        print('Path({}-->{}): '.format(i+1, j+1), end='')
        print_path(i, j)
        print(' cost:', graph[i][j])

在输出中找到1到26的路径
在这里插入图片描述
然后把flag连一连。

BKZ(【红帽杯】primegame)

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from decimal import *
import math
from secret import flag
getcontext().prec = 100

assert (len(flag) == 48)
msg1 = [ord(_) for _ in flag[:24]]
msg2 = [ord(_) for _ in flag[24:]]

primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89]

keys = []
for i in range(len(msg1)):
    keys.append(Decimal(int(primes[i])).ln())

sum_ = Decimal(0.0)
for i, c in enumerate(msg1):
    sum_ += c * Decimal(keys[i])

ct = math.floor(sum_ * 2 ** 256)
print(ct)

sum_ = Decimal(0.0)
for i, c in enumerate(msg2):
    sum_ += c * Decimal(keys[i])

ct = math.floor(sum_ * 2 ** 256)
print(ct)

介个是背包问题,不过不懂
只能未完待续~

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

mxx307

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

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

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

打赏作者

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

抵扣说明:

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

余额充值