UTCTF2024

记录2024UTCTF——Crypto——题解

RSA-256

task

1
2
3
N = 77483692467084448965814418730866278616923517800664484047176015901835675610073
e = 65537
c = 43711206624343807006656378470987868686365943634542525258065694164173101323321

网站分解Nfactordb.com

exp

1
2
3
4
5
6
7
8
9
10
11
from Crypto.Util.number import *

N = 77483692467084448965814418730866278616923517800664484047176015901835675610073
e = 65537
c = 43711206624343807006656378470987868686365943634542525258065694164173101323321
p = 1025252665848145091840062845209085931
q = N // p

d = inverse(e,(p-1)*(q-1))
print(long_to_bytes(pow(c,d,N)))
# utflag{just_send_plaintext}

numbers go brrr

旧附件

task.py

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
#!/usr/bin/env python3
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
import time

seed = int(time.time() * 1000) % (10 ** 6)
def get_random_number():
global seed
seed = int(str(seed * seed).zfill(12)[3:9])
return seed

def encrypt(message):
key = b''
for i in range(8):
key += (get_random_number() % (2 ** 16)).to_bytes(2, 'big')
cipher = AES.new(key, AES.MODE_ECB)
ciphertext = cipher.encrypt(pad(message, AES.block_size))
return ciphertext.hex()

print("Thanks for using our encryption service! To get the encrypted flag, type 1. To encrypt a message, type 2.")
while True:
print("What would you like to do (1 - get encrypted flag, 2 - encrypt a message)?")
user_input = int(input())
if(user_input == 1):
break

print("What is your message?")
message = input()
print("Here is your encrypted message:", encrypt(message.encode()))


flag = open('./src/flag.txt', 'r').read()
print("Here is the encrypted flag:", encrypt(flag.encode()))

以时间作为随机数种子,然后生成AES加密用的密钥key,每次加密用的是不同key

既然每次加密用的是不同的密钥,而且和随机数有关

注意到随机数和时间有关,而我们如果用pwntools连接靶机,那么时间间隔是很小的,可以在连接靶机前的时刻和关闭靶机后的时刻这个范围中爆破seed,然后恢复key

exp.py

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
from tqdm import *
from pwn import *
import time
from Crypto.Cipher import AES

start = int(time.time() * 1000) % (10 ** 6)
sh = remote("betta.utctf.live",7356)

sh.recvuntil(b"What would you like to do (1 - get encrypted flag, 2 - encrypt a message)?")
sh.sendline(b"1")
sh.recvline()
data = sh.recvline()
c = data.decode().split(":")[-1].strip()
c = bytes.fromhex(c)
sh.close()
end = int(time.time() * 1000) % (10 ** 6)

def get_random_number():
global seed
seed = int(str(seed * seed).zfill(12)[3:9])
return seed

for seed in trange(start,end):
key = b''
for i in range(8):
key += (get_random_number() % (2 ** 16)).to_bytes(2, 'big')
aes = AES.new(key, AES.MODE_ECB)
flag = aes.decrypt(c)
if b"utflag" in flag:
print(flag)

新附件

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
#!/usr/bin/env python3
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from Crypto.Random import random

seed = random.randint(0, 10 ** 6)
def get_random_number():
global seed
seed = int(str(seed * seed).zfill(12)[3:9])
return seed

def encrypt(message):
key = b''
for i in range(8):
key += (get_random_number() % (2 ** 16)).to_bytes(2, 'big')
cipher = AES.new(key, AES.MODE_ECB)
ciphertext = cipher.encrypt(pad(message, AES.block_size))
return ciphertext.hex()

print("Thanks for using our encryption service! To get the encrypted flag, type 1. To encrypt a message, type 2.")
while True:
print("What would you like to do (1 - get encrypted flag, 2 - encrypt a message)?")
user_input = int(input())
if(user_input == 1):
break

print("What is your message?")
message = input()
print("Here is your encrypted message:", encrypt(message.encode()))


flag = open('/src/flag.txt', 'r').read();
print("Here is the encrypted flag:", encrypt(flag.encode()))

seed变成$10^6$以内的数,还是爆破

exp

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
from tqdm import *
from pwn import *
from Crypto.Cipher import AES

sh = remote("betta.utctf.live",7356)

sh.recvuntil(b"What would you like to do (1 - get encrypted flag, 2 - encrypt a message)?")
sh.sendline(b"1")
sh.recvline()
data = sh.recvline()
c = data.decode().split(":")[-1].strip()
c = bytes.fromhex(c)
sh.close()

def get_random_number():
global seed
seed = int(str(seed * seed).zfill(12)[3:9])
return seed

for seed in trange(10**6):
key = b''
for i in range(8):
key += (get_random_number() % (2 ** 16)).to_bytes(2, 'big')
aes = AES.new(key, AES.MODE_ECB)
flag = aes.decrypt(c)
if b"utflag" in flag:
print(flag)
break
# utflag{deep_seated_and_recurring_self-doubts}

numbers go brrr 2

task.py

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
#!/usr/bin/env python3
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from Crypto.Random import random

seed = random.randint(0, 10 ** 6)
def get_random_number():
global seed
seed = int(str(seed * seed).zfill(12)[3:9])
return seed

def encrypt(message):
key = b''
for i in range(8):
key += (get_random_number() % (2 ** 16)).to_bytes(2, 'big')
cipher = AES.new(key, AES.MODE_ECB)
ciphertext = cipher.encrypt(pad(message, AES.block_size))
return key.hex(), ciphertext.hex()


print("Thanks for using our encryption service! To get the start guessing, type 1. To encrypt a message, type 2.")
print("You will need to guess the key (you get 250 guesses for one key). You will do this 3 times!")

for i in range(3):
seed = random.randint(0, 10 ** 6)
print("Find the key " + str(i + 1) + " of 3!")
key = encrypt(b"random text to initalize key")[0]
while True:
print("What would you like to do (1 - guess the key, 2 - encrypt a message)?")
user_input = int(input())
if(user_input == 1):
break

print("What is your message?")
message = input()
key, ciphertext = encrypt(message.encode())
print("Here is your encrypted message:", ciphertext)
print("You have 250 guesses to find the key!")

found = False
for j in range(250):
print("What is your guess (in hex)?")
guess = str(input()).lower()
if guess == key:
print("You found the key!")
found = True
break
else:
print("That is not the key!")

if not found:
print("You did not find the key!")
exit(0)


flag = open('/src/flag.txt', 'r').read()
print("Here is the flag:", flag)

要求猜对3次key,我们能够输入明文获取密文,然后key是通过seed生成的,而这个seed范围在$(0,10^6)$,依旧采用爆破的方式

exp

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
from pwn import *
from tqdm import *
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad

def get_random_number():
global seed
seed = int(str(seed * seed).zfill(12)[3:9])
return seed

def encrypt(message):
key = b''
for i in range(8):
key += (get_random_number() % (2 ** 16)).to_bytes(2, 'big')
cipher = AES.new(key, AES.MODE_ECB)
ciphertext = cipher.encrypt(pad(message, AES.block_size))
return key.hex(), ciphertext.hex()

sh = remote("betta.utctf.live",2435)
msg = b"a"*16
sh.recvuntil(b"You will need to guess the key (you get 250 guesses for one key). You will do this 3 times!\n")

for i in range(3):
sh.recvuntil(b"What would you like to do (1 - guess the key, 2 - encrypt a message)?\n")
sh.sendline(b"2")
sh.sendlineafter(b"What is your message?",msg)
sh.recvline()
cipher = sh.recvline().strip().decode().split(":")[-1].strip()

print(f"cipher = {cipher}")
for seed in trange(10**6):
key = b""
for j in range(8):
key += (get_random_number() % (2 ** 16)).to_bytes(2, 'big')
aes = AES.new(key, AES.MODE_ECB)
c = aes.encrypt(pad(msg,AES.block_size)).hex()
if c == cipher:
print(f"key = {key}")
sh.sendline(b"1")
sh.recvuntil(b"What is your guess (in hex)?\n")
sh.sendline(key.hex().encode())
sh.recvline()
break
sh.interactive()
# utflag{ok_you_are_either_really_lucky_or_you_solved_it_as_intended_yay}

Cryptordle

task.py

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
#!/usr/bin/env python3
import random

wordlist = open('/src/wordlist.txt', 'r').read().split('\n')

for word in wordlist:
assert len(word) == 5
for letter in word:
assert letter in 'abcdefghijklmnopqrstuvwxyz'

for attempt in range(3):
answer = random.choice(wordlist)
num_guesses = 0
while True:
num_guesses += 1

print("What's your guess?")
guess = input().lower()

assert len(guess) == 5
for letter in guess:
assert letter in 'abcdefghijklmnopqrstuvwxyz'

if guess == answer:
break

response = 1
for x in range(5):
a = ord(guess[x]) - ord('a')
b = ord(answer[x]) - ord('a')
response = (response * (a-b)) % 31
print(response)
if num_guesses > 6:
print("Sorry, you took more than 6 tries. No flag for you :(")
exit()
else:
print("Good job! Onward...")

if num_guesses <= 6:
print('Nice! You got it :) Have a flag:')
flag = open('/src/flag.txt', 'r').read()
print(flag)
else:
print("Sorry, you took more than 6 tries. No flag for you :(")

猜单词,单词的长度为5,需要我们猜中3次,每次猜谜中有6次机会,如果猜错,靶机会返回我们这样的值:

1
2
3
4
5
6
response = 1
for x in range(5):
a = ord(guess[x]) - ord('a')
b = ord(answer[x]) - ord('a')
response = (response * (a-b)) % 31
print(response)

其实就是$res = (a_1-b_1)\times (a_2-b_2)\times (a_3-b_3)\times (a_4-b_4)\times (a_5-b_5) \mod 31$

我们能够控制$a_1,a_2,a_3,a_4,a_5$

而且有5次机会,刚好5个未知数

我们只需要让每次输入的$a_1,a_2,a_3,a_4,a_5$不同,拿到5个方程,解方程即可获得正确的答案

我分别让$a_i=$1,1,1,1,1,1,1,1,1,2,1,1,1,2,2,1,1,2,2,2,1,2,2,2,2

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# c = [25,28,29,16,15]
# c = [4,16,1,19,7]
# c = [17,18,22,10,2]

R.<x1,x2,x3,x4,x5> = PolynomialRing(Zmod(31))

f1 = (1-x1)*(1-x2)*(1-x3)*(1-x4)*(1-x5) - c[0]
f2 = (1-x1)*(1-x2)*(1-x3)*(1-x4)*(2-x5) - c[1]
f3 = (1-x1)*(1-x2)*(1-x3)*(2-x4)*(2-x5) - c[2]
f4 = (1-x1)*(1-x2)*(2-x3)*(2-x4)*(2-x5) - c[3]
f5 = (1-x1)*(2-x2)*(2-x3)*(2-x4)*(2-x5) - c[4]

F = [f1,f2,f3,f4,f5]
I = Ideal(F)

m1 = ZZ(-I.groebner_basis()[0].univariate_polynomial()(0))
m2 = ZZ(-I.groebner_basis()[1].univariate_polynomial()(0))
m3 = ZZ(-I.groebner_basis()[2].univariate_polynomial()(0))
m4 = ZZ(-I.groebner_basis()[3].univariate_polynomial()(0))
m5 = ZZ(-I.groebner_basis()[4].univariate_polynomial()(0))

m = chr(m1+97)+chr(m2+97)+chr(m3+97)+chr(m4+97)+chr(m5+97)
print(m)

分别对应的结果是triedcanalskimp

flag:utflag{sometimes_pure_guessing_is_the_strat}

bits and pieces

task

1
2
3
4
5
6
7
8
9
10
11
n1: 16895844090302140592659203092326754397916615877156418083775983326567262857434286784352755691231372524046947817027609871339779052340298851455825343914565349651333283551138205456284824077873043013595313773956794816682958706482754685120090750397747015038669047713101397337825418638859770626618854997324831793483659910322937454178396049671348919161991562332828398316094938835561259917841140366936226953293604869404280861112141284704018480497443189808649594222983536682286615023646284397886256209485789545675225329069539408667982428192470430204799653602931007107335558965120815430420898506688511671241705574335613090682013
e1: 65537
c1: 7818321254750334008379589501292325137682074322887683915464861106561934924365660251934320703022566522347141167914364318838415147127470950035180892461318743733126352087505518644388733527228841614726465965063829798897019439281915857574681062185664885100301873341937972872093168047018772766147350521571412432577721606426701002748739547026207569446359265024200993747841661884692928926039185964274224841237045619928248330951699007619244530879692563852129885323775823816451787955743942968401187507702618237082254283484203161006940664144806744142758756632646039371103714891470816121641325719797534020540250766889785919814382

n2: 22160567763948492895090996477047180485455524932702696697570991168736807463988465318899280678030104758714228331712868417831523511943197686617200545714707332594532611440360591874484774459472586464202240208125663048882939144024375040954148333792401257005790372881106262295967972148685076689432551379850079201234407868804450612865472429316169948404048708078383285810578598637431494164050174843806035033795105585543061957794162099125273596995686952118842090801867908842775373362066408634559153339824637727686109642585264413233583449179272399592842009933883647300090091041520319428330663770540635256486617825262149407200317
e2: 65537
c2: 19690520754051173647211685164072637555800784045910293368304706863370317909953687036313142136905145035923461684882237012444470624603324950525342723531350867347220681870482876998144413576696234307889695564386378507641438147676387327512816972488162619290220067572175960616418052216207456516160477378246666363877325851823689429475469383672825775159901117234555363911938490115559955086071530659273866145507400856136591391884526718884267990093630051614232280554396776513566245029154917966361698708629039129727327128483243363394841238956869151344974086425362274696045998136718784402364220587942046822063205137520791363319144

n3: 30411521910612406343993844830038303042143033746292579505901870953143975096282414718336718528037226099433670922614061664943892535514165683437199134278311973454116349060301041910849566746140890727885805721657086881479617492719586633881232556353366139554061188176830768575643015098049227964483233358203790768451798571704097416317067159175992894745746804122229684121275771877235870287805477152050742436672871552080666302532175003523693101768152753770024596485981429603734379784791055870925138803002395176578318147445903935688821423158926063921552282638439035914577171715576836189246536239295484699682522744627111615899081
e3: 65537
c3: 17407076170882273876432597038388758264230617761068651657734759714156681119134231664293550430901872572856333330745780794113236587515588367725879684954488698153571665447141528395185542787913364717776209909588729447283115651585815847333568874548696816813748100515388820080812467785181990042664564706242879424162602753729028187519433639583471983065246575409341038859576101783940398158000236250734758549527625716150775997198493235465480875148169558815498752869321570202908633179473348243670372581519248414555681834596365572626822309814663046580083035403339576751500705695598043247593357230327746709126221695232509039271637

n2,n3存在公因数,完成分解

n1用yafu分解

exp

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
import gmpy2
from Crypto.Util.number import *

n1 = 16895844090302140592659203092326754397916615877156418083775983326567262857434286784352755691231372524046947817027609871339779052340298851455825343914565349651333283551138205456284824077873043013595313773956794816682958706482754685120090750397747015038669047713101397337825418638859770626618854997324831793483659910322937454178396049671348919161991562332828398316094938835561259917841140366936226953293604869404280861112141284704018480497443189808649594222983536682286615023646284397886256209485789545675225329069539408667982428192470430204799653602931007107335558965120815430420898506688511671241705574335613090682013
e1 = 65537
c1 = 7818321254750334008379589501292325137682074322887683915464861106561934924365660251934320703022566522347141167914364318838415147127470950035180892461318743733126352087505518644388733527228841614726465965063829798897019439281915857574681062185664885100301873341937972872093168047018772766147350521571412432577721606426701002748739547026207569446359265024200993747841661884692928926039185964274224841237045619928248330951699007619244530879692563852129885323775823816451787955743942968401187507702618237082254283484203161006940664144806744142758756632646039371103714891470816121641325719797534020540250766889785919814382

n2 = 22160567763948492895090996477047180485455524932702696697570991168736807463988465318899280678030104758714228331712868417831523511943197686617200545714707332594532611440360591874484774459472586464202240208125663048882939144024375040954148333792401257005790372881106262295967972148685076689432551379850079201234407868804450612865472429316169948404048708078383285810578598637431494164050174843806035033795105585543061957794162099125273596995686952118842090801867908842775373362066408634559153339824637727686109642585264413233583449179272399592842009933883647300090091041520319428330663770540635256486617825262149407200317
e2 = 65537
c2 = 19690520754051173647211685164072637555800784045910293368304706863370317909953687036313142136905145035923461684882237012444470624603324950525342723531350867347220681870482876998144413576696234307889695564386378507641438147676387327512816972488162619290220067572175960616418052216207456516160477378246666363877325851823689429475469383672825775159901117234555363911938490115559955086071530659273866145507400856136591391884526718884267990093630051614232280554396776513566245029154917966361698708629039129727327128483243363394841238956869151344974086425362274696045998136718784402364220587942046822063205137520791363319144

n3 = 30411521910612406343993844830038303042143033746292579505901870953143975096282414718336718528037226099433670922614061664943892535514165683437199134278311973454116349060301041910849566746140890727885805721657086881479617492719586633881232556353366139554061188176830768575643015098049227964483233358203790768451798571704097416317067159175992894745746804122229684121275771877235870287805477152050742436672871552080666302532175003523693101768152753770024596485981429603734379784791055870925138803002395176578318147445903935688821423158926063921552282638439035914577171715576836189246536239295484699682522744627111615899081
e3 = 65537
c3 = 17407076170882273876432597038388758264230617761068651657734759714156681119134231664293550430901872572856333330745780794113236587515588367725879684954488698153571665447141528395185542787913364717776209909588729447283115651585815847333568874548696816813748100515388820080812467785181990042664564706242879424162602753729028187519433639583471983065246575409341038859576101783940398158000236250734758549527625716150775997198493235465480875148169558815498752869321570202908633179473348243670372581519248414555681834596365572626822309814663046580083035403339576751500705695598043247593357230327746709126221695232509039271637

n = [n1,n2,n3]
c = [c1,c2,c3]
for i in range(3):
for j in range(3):
if i != j:
p = gmpy2.gcd(n[i],n[j])
if p != 1:
print(p)


p = 175136386393724074897068211302311758514344898633187862983126380556807924872210372704023620020763131468811275018725481764101835410780850364387004844957680252860643364609959757601263568806626614487575229052115194838589297358422557307359118854093864998895206960681533165623745478696564104830629591040860031236467
p1 = 129984014749130366259742130443330376923069118727641845190136006048911945242427603092160936004682857611235008521722596025476170673607376869837675885556290582081941522328978811710862857253777650447221864279732376499043513950683086803379743964370215090077032772967632331576620201195241241611325672953583711299819

q1 = n1 // p1
q2 = n2 // p
q3 = n3 // p
d1 = gmpy2.invert(e1,(p1-1)*(q1-1))
d2 = gmpy2.invert(e2,(p-1)*(q2-1))
d3 = gmpy2.invert(e3,(p-1)*(q3-1))
m1 = pow(c1,d1,n1)
m2 = pow(c2,d2,n2)
m3 = pow(c3,d3,n3)
flag = long_to_bytes(m1) + long_to_bytes(m2) + long_to_bytes(m3)
print(flag)
# utflag{oh_no_it_didnt_work_</3_i_guess_i_can_just_use_standard_libraries_in_the_future}

simple signature

nc betta.utctf.live 4374

这道题目没有附件,连上靶机发现是个RSA签名生成器

Welcome to the signature generator!
This service generates signatures for nonnegative integer messages.
Today’s RSA parameters are:

n = …

e = …

首先我们需要知道RSA签名的过程:
$$
sign \equiv h(m)^d \mod n
$$
这里m就是我们的明文消息,而h代表哈希函数,d代表我们平常的解密私钥

验证签名的过程是用公钥e进行的
$$
v \equiv sign^e \mod n
$$
本题我测试(测试如下)过发现,签名过程并不是对哈希后的明文消息进行签名,而是直接用m进行签名

我输入2之后,返回的签名是

1
19305047859578018954980116599753882711666480484142979465593383963718233040355590155869672573524217910051341399926166313215438016944909841325609661233708867343163708635690290325145359946697142164401814696198967248480534658338503630656123368239008794161223488100051552078603748861066699059542173080955664314245942352900854926237713096042527712292770988034717809771051464470887040552525974670894693177946816058097139433917736749106750964478978103361323385114107986313741317398412086531210680773102594971067051466113817094724683640177915480168931380713903297694652708554062155884806690502249638131714247467724175797421627

进行验证pow(s,e,n) = 2

既然不是对哈希后的明文消息进行签名,那么很容易实现签名伪造

已知
$$
s_1 \equiv m_1^d \mod n
$$

$$
s_2 \equiv m_2^d \mod n
$$

我们将两个签名相乘得到
$$
s_1 \times s_2 \equiv (m_1\times m_2)^d \mod n
$$
这相当于$s_3 \equiv m_3^d \mod n$

验证签名的时候会有$m_3 \equiv (s_1\times s_2)^e \equiv ((m_1\times m_2)^d)^e \equiv m_1\times m_2 \mod n$

通过这个我们即可实现伪造攻击

参考:RSA签名伪造_51CTO博客_伪造签名

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
└─$ nc betta.utctf.live 4374
Welcome to the signature generator!
This service generates signatures for nonnegative integer messages.
Today's RSA parameters are:
n = 22715415800845998993024248030912907934417610887661897677054217214410204092730320049883830649576833798235714524267550954257998402694512553806347540563817503765200000540567467194229934670132595181693756907560598419504853644981230926968934508408798411039604272013286354235309604897737849867286894191734498426882265991962178303977297297251166823420641597385760024527882951963763449900905583806374810182746133330897953973605976893360656996077027444918972375454537579314357093723161232116480999012805953845834378812517394470647495652867705481169517276997801093879183367121124675601652536608512214606801800156081683634353613
e = 65537
Enter a message as an integer (enter 0 to stop): 2
Your signature is: 19305047859578018954980116599753882711666480484142979465593383963718233040355590155869672573524217910051341399926166313215438016944909841325609661233708867343163708635690290325145359946697142164401814696198967248480534658338503630656123368239008794161223488100051552078603748861066699059542173080955664314245942352900854926237713096042527712292770988034717809771051464470887040552525974670894693177946816058097139433917736749106750964478978103361323385114107986313741317398412086531210680773102594971067051466113817094724683640177915480168931380713903297694652708554062155884806690502249638131714247467724175797421627
Enter a message as an integer (enter 0 to stop): 3
Your signature is: 12466668289899335464133090475657405950931821501533663001516736457824416177523171645577410125680582801199031807950155805989703649370706570876105560672722786621599217384752567820542034014172784328764628129021815078333759824898640044024669060187741947696361614188900150657553950899178216102406146022841319632133901664545580403590911676417478329981850274513600128209610835989969785039648356553422593375047160549502704081296610218123751535810888825205063182213809953668870294813497134950692299358898522409282459702028599784084273165843672444206386732642592570271106680551501845998454554339849461050571639928425405734311733
Enter a message as an integer (enter 0 to stop): 0
Now, come up with your own pair!
Enter a message: 6
Enter a signature: 18982512873975173404933208419297386148920412591312317190999194687782049821680066612137323122655631365467978106391805163213875322096115052965353281855431718650033207890296554899233461063309157149813467505339311987308434971353194958650326478611180026442531262465134575047863754669782250309134800418243005941952440587177890885709176439351435995900545760925916705390507936161719544350561690754688037652781517684043996183726063988733579686454511426639010681269324482585239497278113727930739428354647428514162145491240213537530578274699904468976840913094523715136698577665810122637986259264550250518723399900126769899559214
Congrats! Here is the flag: utflag{a1m05t_t3xtb00k_3x3rc153}
-------------已经到底啦!-------------