这里就对mix这题进行记录

mix

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
from Crypto.Util.number import *

from secret import flag

import random

p = getStrongPrime(2048)

q = getStrongPrime(2048)

s = getStrongPrime(2048)

r = int(裴波那契数列[2022])

mask = b'******'

enc1 = b'******'

flag1 = b'CMCTF{' +enc1 + mask + b'}'

e = 0o10001

m = bytes_to_long(enc1)

n = p * q * r

c = pow(m, e, n)

hint = p*s*q - p*s - q*s + s

print('n=',n)

print('c=',c)

print('hint=',hint)

\# n= 121445040208861909069894403265135678065120910909862499020293974222353911252357668566443655271324561444629423085857365441663340335267122084303353024719970701684304078915449107665234153848865575171396266594850387632166116876666641345151524526093750743311423760629508920605398826413219456966060130654182319239622853235598419783244961101023565485613969127617211798200257784669487075518232217287821539002272955530731559925743819394303592463643472505544371511975391525417372030795124188756668359793712687313915869489834990149406102691674251037529200092462351869985445609978956083451480606196410709785266414297484270955804000909874710243291131008074987501840685895810982539715865808340785585783784932746009294793388111303497827361597667080060904233538640411944294069905932767542941079924615545492728930748632793138167526456821615565265643786589492447320384175015988885891762397927722597983943795776730381090838150325379769514627877859254280292596379986317145513592309694492391589942506965514462458275558089505709047707881858666740272995276712061033659325342969092555904181602954831675187019667837919000590097455240471706803903843864588874240819424978016149001940435459574272517121404191497401282693543020081054458057536135286337530413794162493772935203185468003808946179794587532129108140773036801981194625504026220172240941266669713633255771146945596494369563639162958148338997083151465760140380287388970013418518808560606190028648382869570465274426248220666799284598328143667941885780739645827723387774853960763697674935365788526188525877728188039212192465886463099601345762532695705673402546191349122040406356859512156595066368962709427340711912079526354041896

\# c= 56588793843319337746724191421797882919298382185789212342757993436535833538835522763229763594877667021903450245810685457239006347519758531527469886935960286141037132766391893854072489010976740737632329381497939974348685705638979763163979105135831966969462502212645331623912058124799565947994143213185185992532880019990646317265334164877775033560523059626818443959011448004361903639117592816084037679180458435582475302588998924848174547895790261541575925513887774899878433973389508964314168199120579798596134069816522786705872922325579820616825662181444792078041146420951204474840017339067144121627577361659204068184374437536021834866744629203173525452975550210170854689131249911980147698258676007773287058650732712430646538052932526385903664366173103845251460027428058991440409897707266114313760974556093019272676530729679647453145281642248231912623556282846880428854082954278583510952137984285948462279982465734721299949983519379129012579754979967314981583010596156968017750652218444293183553797064562640415021018922337530706623720329914512691891247157484346793520829716469015298628414649436647705362645773660510066453649321698837054590345696220371667776079460869975651358713981526804058124260167477067800116925869645048296793453667948263141449977001998111471446893535134204947903797920023508228450635623912282556920844859004265256776076205404744691901113660811077768891817723583726923916755419376617397161631255119342712941347511133994305902274463032094437850518737799347513359266736626688000378302129740278671252372100118745385045165006411579452656230211530847834481096650640749089767353846648834690606914589383720715808010950418989797804848844908028168

\# hint= 18294419705033749803018183186096112152402551291430209346583558472922013290690589800566513840852313152850815949693453061822473006436564091423275427734726183402882773876530619900017570008504487011496639900712276814180156892043893283337592870931604509182121126729757414875305980944401674021305109901787373919069250888132010941446377885033954783641074524904335530439232153795506796131799840815859332631629520548237546341180970993275196594743629686044240376562797833663497706050016975314637814732243863519275581657562824577416520887857531300484034288184348876435266599982852899863511077867993896260185876623577916847805434018960645048222193073045995417189741052112103530337456864569791619370910540989544825643388189316375353130601280427411097634982360164150650121200938121132975127392218810406251814769876585467670838768851084325019437401290895892649127468159357644376855642219871658242665316842174539950982501562012993620707848235840777465439382427694385975143409696608524006610718341269938590805893846551221772802799937388082484101818519470210469287886673559139819764993972650754106595274703362578095021666440413181006787169326119053179113634896719904706459255688323355422629750624744361016321749825711352381979526373745414466117496901188899402968884557897042915393081588659355938084179373516472500982821481620361825619098189709268749353026527626333126253300709023279752604686313218745191179635948042935114535230124092175888272591892209973826349925162305622280085164752927856768903063667002948252367704955505382627077430221515644243237639648659331074231756506975066652222700589414902433234306276129685280949801672748996080027431076564977892352264341740524147048337215454135414149313442308392992893543348489794522704133497959650612938856771407888345435215493938925195892269263980872231297338970570968594859288833461843787177471203855945919703978692377984

def lfsr(R, mask):

output = (R << 1) & 0xffffffffffffffffffffffffffffffff

i = (R & mask) & 0xffffffffffffffffffffffffffffffff

lastbit=0

while i != 0:

lastbit ^= (i & 1)

i = i >> 1

output ^= lastbit

return (output,lastbit)

num_mask = bytes_to_long(mask)

R = random.getrandbits(128)

print(R)

for _ in range(128):

R,out = lfsr(R,num_mask)

print(R)

# 176011035589551066670092363165068881602

# 157117237038314150714243518116791116977

对于第一部分来说我们需要先求出r

1
r = int(裴波那契数列[2022])

条件中给出我们要求的是fib(2022),这里有多种方法可以求解,暴力递归或者DP或者矩阵快速幂

这里暴力递归的时间复杂度是O(2N)

DP的时间复杂度是O(N)

矩阵快速幂的时间复杂度是O(logN

这里介绍下如何用快速幂来求斐波那契数列的第n项

对于斐波那契数列我们知道 fn = fn − 1 + fn − 2 这个数列是这个样子的 0,1,1,2,3,5,8… 首先我们先定义向量$\vec{v1}$$\vec{v2}$ $$ v1=\begin{pmatrix} 0\\ 1 \end{pmatrix} $$

$$ v2=\begin{pmatrix} 1\\ 1 \end{pmatrix} $$

这里我们可以看作$\vec{v1}$通过左乘一个矩阵得到了$\vec{v2}$,即 $$ \begin{pmatrix} a & b\\ c &d \end{pmatrix} \begin{pmatrix} 0\\ 1 \end{pmatrix}=\begin{pmatrix} 1\\ 1 \end{pmatrix} $$ 这里要解除参数a,b,c,d我们就还需要一组 $$ \begin{pmatrix} a & b\\ c &d \end{pmatrix} \begin{pmatrix} 1\\ 1 \end{pmatrix}=\begin{pmatrix} 1\\ 2 \end{pmatrix} $$ 根据矩阵的乘法就可以知道

a=0 b=1 c=1 d=1,那么M矩阵也就出来了 $$ \begin{pmatrix} a & b\\ c &d \end{pmatrix}= \begin{pmatrix} 0 & 1\\ 1 &1 \end{pmatrix} $$ 我们想求第n项,就变成了M的n-1次方乘上v1

现在问题就转换成了求一个矩阵的高次幂

先看传统的快速幂是如何求解的

假设现在要求的是353

将53转换成二进制也就是110101

把二进制位上不为0的数表示出来就会得到 332 * 316 * 34 * 31 = 353 那么对于矩阵来说也是如此

回到本题,要求的是第2022项

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
def matrix_mult(A, B):

"""2x2 矩阵乘法"""

return [

[A[0][0] * B[0][0] + A[0][1] * B[1][0], A[0][0] * B[0][1] + A[0][1] * B[1][1]],

[A[1][0] * B[0][0] + A[1][1] * B[1][0], A[1][0] * B[0][1] + A[1][1] * B[1][1]],

]

def matrix_pow(mat, power):

"""矩阵快速幂"""

result = [[1, 0], [0, 1]] # 单位矩阵,区别于普通的快速幂初始的我们要取单位矩阵

while power > 0:

if power % 2 == 1:

result = matrix_mult(result, mat)

mat = matrix_mult(mat, mat)

power //= 2

return result

def fibonacci(n):

if n == 0:

return 0

mat = [[1, 1], [1, 0]]

mat_pow = matrix_pow(mat, n - 1)

return mat_pow[0][0]

print(fibonacci(2022)) # 输出 fib(2022)

这里用DP的代码是

1
2
3
4
5
6
7
8
9
10
11
12
def fibonacci(n):
if n == 0:
return 0


a, b = 0, 1 # a = fib(0), b = fib(1)
for _ in range(2, n + 1):
a, b = b, a + b # 滚动更新

return b

print(fibonacci(2022)) # 输出 fib(2022)
1
r=167310648784659280728144836725590014814177400797476760876753704080114260114536495380135014244628641540465009479015934299376306193238817784129405465804445140758993423687143146613390123354557936785042721146861530732824681611737331775039385078670522766530356710254069894988375176317365030278080713218413201048678360636199830514037131301419749286901789895779518426772646405033423571360115994228553098871046696520981384561779336

我们还知道 hint = p * s * q − p * s − q * s + s

hint = s * (n − p − q + 1)

也就是hint是phi的倍数

所以我可以直接求出私钥

1
2
3
4
5
6
7
8
9
10
11
e = 0o10001

d = pow(e, -1, hint)

m = pow(c, d, n)

enc1 = long_to_bytes(m)

print(enc1)


第二部分是LFSR

这里的LFSR是已经输入和输出要求掩码mask,所以可以通过解方程来实现求解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
def init(state):

result = [int(i) for i in bin(state)[2:]]

PadLenth = 128 - len(result)

result = [ 0 ] * PadLenth + result

assert len(result) == 128

return result



def solve_GF2_linear_system(A, b):

"""

使用 SageMath 在 GF(2) 上求解线性方程组 Ax = b

:param A: 系数矩阵

:param b: 结果向量

:return: 解向量 x

"""

F = GF(2)

A_GF2 = Matrix(F, A)

b_GF2 = vector(F, b)



try:

x = A_GF2.solve_right(b_GF2)

return x

except ValueError:

return None



def solution(m):

a,b = m[0],m[1]

solution = solve_GF2_linear_system(a, b)

if solution:

print(f"解向量为: {solution}")

return solution

else:

print("无解")

return None



def change(seed,random):

All = seed + random

a = [[0]*128 for _ in range(128)]

b = random

for i in range(128):

a[i] = All[i:i+128]

return (a,b)



random1 = 176011035589551066670092363165068881602

random2 = 157117237038314150714243518116791116977



random1,random2 = map(init, [random1,random2])



ans = solution(change(random1,random2))

mask = int("".join(str(i) for i in ans),2)

mask = long_to_bytes(int(mask))

print(mask) # B1e_ju@n_le_QAQ!