# BUUCTF 每日打卡 2021-5-11

crypto 专栏收录该内容
79 篇文章 1 订阅

## [2021 红帽杯]primegame

#!/usr/bin/env python3

from decimal import *
import math
import random
import struct

from flag import flag

primes = [2]
for i in range(3, 100):
f = True
for j in primes:
if i * i < j:
break
if i % j == 0:
f = False
break
if f:
primes.append(i)

# Random shuffle the primes
# Now you cannot know the order
seed = struct.unpack('<i', flag[5:9])[0]
random.seed(seed)
random.shuffle(primes)

# Use ln function
# Now you cannot know the key itself
getcontext().prec = 100
keys = []
for i in range(len(flag)):
keys.append(Decimal(primes[i]).ln())

# Sum values
# Now you cannot know the flag
sum_ = Decimal(0.0)
for i, c in enumerate(flag):
sum_ += c * Decimal(keys[i])

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


1、查找不超过100的素数。（共25个）
2、通过使用 flag 的第6到第9字节作为随机种子，可以对十进制素数数组进行改组。
3、每个改组的素数都取以 e 为底的对数，十进制精度为100。
4、将上一步得到的 ln 值乘以标记的每个字节所获得的值相加，乘以 2 ** 256 然后四舍五入。

#!/usr/bin/env python3

from decimal import *
import math
import random
import struct
from flag import flag

assert (len(flag) == 48)
msg1 = flag[:24]
msg2 = flag[24:]
primes = [2]
# 获取 [2,90] 的素数
for i in range(3, 90):
f = True
for j in primes:
if i * i < j: # i^2 >= j
break
if i % j == 0:
f = False
break
if f:
primes.append(i)

getcontext().prec = 100 # 保留 100 位小数
keys = []
for i in range(len(msg1)): # len(primes) = 24
keys.append(Decimal(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)
# 597952043660446249020184773232983974017780255881942379044454676980646417087515453
sum_ = Decimal(0.0)
for i, c in enumerate(msg2):
sum_ += c * Decimal(keys[i])

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


wp 的解法也都是转化为对两段分别进行背包问题求解

### Peonix dl 解法

dl 的手稿：

from decimal import *
import math

flag = []
for i in range(48*8):
flag.append(0)
assert (len(flag) == 48*8)
msg1 = flag[:24*8]
msg2 = flag[24*8:]
primes = [2]
for i in range(3, 90):
f = True
for j in primes:
if i * i < j:
break
if i % j == 0:
f = False
break
if f:
primes.append(i)

getcontext().prec = 100
keys = []
for i in range(len(msg1)):
keys.append(math.floor(2 ** 256 * (2 ** (i % 8)) * Decimal(primes[i//8]).ln()))
print(keys)


### 原题解法

from decimal import *

getcontext().prec = int(100)

primes = [2]
for i in range(3, 100):
f = True
for j in primes:
if i * i < j:
break
if i % j == 0:
f = False
break
if f:
primes.append(i)

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

arr = []
for v in keys:
arr.append(int(v * int(16) ** int(64)))

ct = 737384863737803670841307970259513146291422299366557325168325233349136771464845311
#ct = 425985475047781336789963300910446852783032712598571885345660550546372063410589918

# sage代码：
def encrypt(res):
h = Decimal(int(0))
for i in range(len(keys)):
h += res[i] * keys[i]

ct = int(h * int(16)**int(64))
return ct

def f(N):
ln = len(arr)
A = Matrix(ZZ, ln + 1, ln + 1)
for i in range(ln):
A[i, i] = 1
A[i, ln] = arr[i] // N
A[ln, i] = 64

A[ln, ln] = ct // N

res = A.LLL()

for i in range(ln + 1):
flag = True
for j in range(ln):
if -64 <= res[i][j] < 64:
continue
flag = False
break
if flag:
vec = [int(v + 64) for v in res[i][:-1]]
ret = encrypt(vec)
if ret == ct:
print(N, bytes(vec))
else:
print("NO", ret, bytes(vec))

for i in range(2, 10000):
print(i)
f(i)


## 结语

• 0
点赞
• 0
评论
• 1
收藏
• 打赏
• 扫一扫，分享海报

07-02 1086
08-27 8073
09-11 77
04-09 514
03-12 353
01-03
05-07 2308
08-06 259
03-31 1688
09-17 557
04-28 5791
08-23 751

Σ2333!

¥2 ¥4 ¥6 ¥10 ¥20

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