当前位置:   article > 正文

2024春秋杯网络安全联赛夏季赛Crypto(AK)解题思路及用到的软件

2024春秋杯网络安全联赛夏季赛Crypto(AK)解题思路及用到的软件

2024春秋杯网络安全联赛夏季赛Crypto(AK)

2024春秋杯网络安全联赛夏季赛Crypto解题思路以及用到的软件

所有题用到的软件

1.vm(虚拟机kali)和Ubuntu,正常配置即可B站有很多。

2.Visual Studio Code(里面要配置python,crypto库和Sagemath数学软件系统Sagemath)。

3.随波逐流工作室 (1o1o.xyz)ctf工具。

ezzzecc

原题代码

  1. p = getPrime(256)
  2. a = getPrime(256)
  3. b = getPrime(256)
  4. E = EllipticCurve(GF(p),[a,b])
  5. m = E.random_point()
  6. G = E.random_point()
  7. k = getPrime(18)
  8. K = k * G
  9. r = getPrime(256)
  10. c1 = m + r * K
  11. c2 = r * G
  12. cipher_left = s2n(flag[:len(flag)//2]) * m[0] #flag的前半部分乘m[0],所以只要用密文的除于m[0]即可得到flag前半部分
  13. cipher_right = s2n(flag[len(flag)//2:]) * m[1] #flag的后半部分点乘m[1]
  14. p = p的格式为p={p}koZP3YQAklARRNrmYfjxoKIAXegOcG4jMOmKb08uESOkCCn72d6UM2NWgefYPEMq4EJ1M0jKaqt02Guo5Ubccjqg4QZaaHbScREx38UMLQKwG0LcDd8VFX1zkobc1ZQn4L3DhKQrgJZI55todgOdJuHN532bxScAvOF26gJyQclPtRHn3M6SHrRCEXzzmszd68PJlLB6HaabrRrCW9ZoAYSZetM5jDBtNCJLpR0CBZUUk3Oeh2MZQu2vk8DZ1QqNG49hlxGfawp1FXvAZPdMwixzkhEQnbCDcOKzYyT6BZF2Dfd940tazl7HNOswuIpLsqXQ2h56guGngMeYfMXEZV09fsB3TE0N934CLF8TbZnzFzEkOe8TPTK2mWPVSrgmbsGHnxgYWhaRQWg3yosgDfrEa5qfVl9De41PVtTw024gltovypMXK5XMhuhogs0EMN7hkLapLn6lMj
  15. K = (49293150360761418309411209621405185437426003792008480206387047056777011104939 : 43598371886286324285673726736628847559547403221353820773139325027318579443479)
  16. G = (34031022567935512558184471533035716554557378321289293120392294258731566673565 : 74331715224220154299708533566163247663094029276428146274456519014761122295496)
  17. 私钥k小于1000000
  18. c1 = (3315847183153421424358678117707706758962521458183324187760613108746362414091 : 61422809633368910312843316855658127170184420570309973276760547643460231548014)
  19. c2 = (12838481482175070256758359669437500951915904121998959094172291545942862161864 : 60841550842604234546787351747017749679783606696419878692095419214989669624971)
  20. cipher_left = 75142205156781095042041227504637709079517729950375899059488581605798510465939
  21. cipher_right = 61560856815190247060747741878070276409743228362585436028144398174723191051815

解题思路(先解析给的条件接着再看要求)

  1. 确定椭圆曲线参数和点

    • 椭圆曲线的参数 ( p )、( a )、( b ) 已经给出。
    • 点 ( G )、( K )、( c1 )、( c2 ) 也已经给出。
  2. 计算私钥 ( k )

    • 私钥 ( k ) 是一个小于 1000000 的素数。
    • 我们知道 ( K = k \cdot G ),所以可以通过遍历所有可能的 ( k ) 值来找到正确的 ( k )。
  3. 计算明文点 ( m )

    • 我们知道 ( c1 = m + r \cdot K ) 和 ( c2 = r \cdot G )。
    • 通过 ( c2 = r \cdot G ),我们可以计算出 ( r )。
    • 然后使用 ( r ) 和 ( K ) 计算 ( r \cdot K )。
    • 最后,通过 ( c1 - r \cdot K ) 计算出 ( m )。
  4. 解密 flag

    • 使用 ( m ) 的坐标 ( m[0] ) 和 ( m[1] ) 来解密 cipher_left 和 cipher_right

脚本如下

  1. #from sage.all import * # 导入SageMath的所有功能,但在此代码中未使用
  2. from Crypto.Util.number import * # 导入Crypto库中的实用函数
  3. # 定义椭圆曲线参数
  4. a = 87425770561190618633288232353256495656281438408946725202136726983601884085917
  5. b = 107879772066707091306779801409109036008421651378615140327877558014536331974777
  6. p = 95258468765219141626168727997935766803481277588106799359407486570046359762703
  7. # 打印p的二进制长度
  8. print(len(bin(p)))
  9. # 定义椭圆曲线E
  10. E = EllipticCurve(GF(p), [a, b])
  11. # 打印椭圆曲线E的阶(点的数量)
  12. print(E.order())
  13. # 定义密文部分
  14. cipher_left = 75142205156781095042041227504637709079517729950375899059488581605798510465939
  15. cipher_right = 61560856815190247060747741878070276409743228362585436028144398174723191051815
  16. # 定义椭圆曲线上的点c1和c2
  17. c1 = E(3315847183153421424358678117707706758962521458183324187760613108746362414091, 61422809633368910312843316855658127170184420570309973276760547643460231548014)
  18. c2 = E(12838481482175070256758359669437500951915904121998959094172291545942862161864, 60841550842604234546787351747017749679783606696419878692095419214989669624971)
  19. # 尝试不同的k值来解密
  20. for k in range(1000000):
  21. m = c1 - k * c2 # 计算m = c1 - k * c2
  22. flag1 = long_to_bytes(int(cipher_left / m[0])) # 将cipher_left除以m的x坐标并转换为字节
  23. flag2 = long_to_bytes(int(cipher_right / m[1])) # 将cipher_right除以m的y坐标并转换为字节
  24. if b'flag' in flag1 or b'ctf' in flag1: # 检查是否包含'flag'或'ctf'
  25. print(flag1 + flag2) # 打印解密结果
  26. break # 找到结果后退出循环

解密的关键在于找到一个合适的 k 值,这个 k 值的范围是从 0 到 999999。对于每一个 k,我们计算 m = c1 - k * c2

接着,我们把 cipher_left 和 cipher_right 分别除以 m 的 x 坐标和 y 坐标,得到两个字节串 flag1 和 flag2

最后一步,我们检查一下 flag1 里面有没有包含关键字 b'flag' 或者 b'ctf'。如果有的话,我们就把 flag1 和 flag2 拼接起来,输出完整的 flag。

视频讲解: 

2024春秋竞赛ezzzecc视频解题思路

flag 

happy2024

原题代码1

  1. from not2022but2024 import CBC_key # 从not2022but2024模块导入CBC_key
  2. from Crypto.Util.Padding import pad # 从Crypto库导入填充函数
  3. flag = b'flag{}' # 定义一个字节串形式的flag
  4. from Crypto.Cipher import AES # 从Crypto库导入AES加密模块
  5. from hashlib import sha256 # 从hashlib库导入sha256哈希函数
  6. import random # 导入随机数生成模块
  7. n = 92409623123098901791792363114697204166734358914220895740223341612682462563324908002852969747447253269353656265717157699071118377228204036796781052853910448495779756732335396395768081489079058079814549547598374174800251028951681229956305213989996252604809845148110414284348919868084631304579378411884754210093
  8. m = 80 # 定义一个整数m
  9. M = random_prime(2^256) # 生成一个256位的随机素数M
  10. As = [random.randrange(0, M) for i in range(n)] # 生成n个在0到M之间的随机数
  11. xs = [random_vector(GF(2), m).change_ring(ZZ) for i in range(n)] # 生成n个随机向量,每个向量有m个元素
  12. Bs = sum([As[_] * vector(Zmod(M), xs[_]) for _ in range(n)]).change_ring(ZZ) # 计算Bs,它是As和xs的线性组合
  13. IV = sha256(str(int(sum(As))).encode()).digest()[:16] # 使用sha256哈希函数生成IV,取前16字节
  14. aes = AES.new(CBC_key, AES.MODE_CBC, iv=IV) # 创建AES加密对象,使用CBC模式和生成的IV
  15. cipher = aes.encrypt(pad(flag, 16)) # 使用AES加密flag,并进行填充
  16. print(cipher) # 打印加密后的密文
  17. print(Bs) # 打印Bs的值
  18. print(M) # 打印M的值

原题代码2

  1. from Crypto.Util.number import * # 导入Crypto库中的实用函数
  2. CBC_key = b'' # 初始化CBC模式的密钥,目前为空字节串
  3. p,q = getPrime(512),getPrime(512) # 生成两个512位的素数p和q
  4. n = p * q # 计算n,即p和q的乘积
  5. N = n**2 + 2024 # 计算N,即n的平方加上2024
  6. hint = (pow(3, 2022, N) * p**2 + pow(5, 2022, N) * q**2) % N
  7. # 计算hint,使用3的2022次方模N乘以p的平方加上5的2022次方模N乘以q的平方,然后对N取模
  8. c = pow(bytes_to_long(CBC_key), 65537, n) # 将CBC_key转换为长整数,然后计算其65537次方模n,得到密文c
  9. print('n =', n) # 打印n的值
  10. print('h =', hint) # 打印hint的值
  11. print('c =', c) # 打印密文c的值

解题思路(先解析给的条件接着再看要求)

首先,我们需要从打印的输出中获取加密后的密文。这个密文是使用AES加密算法生成的。接下来,我们需要计算初始化向量(IV)。IV是通过对As列表中的所有元素求和,并将结果转换为字符串后进行SHA-256哈希,然后取前16字节生成的。我们还需要知道用于加密的密钥(CBC_key)。这个密钥是从not2022but2024模块中导入的。最后,我们使用AES解密对象和IV来解密密文。创建AES解密对象时,使用CBC模式和生成的IV。然后,使用解密对象对密文进行解密,并去除填充,得到原始的flag。

  1. 导入必要的模块和定义变量

    • not2022but2024模块导入CBC_key
    • Crypto库导入填充函数pad
    • 定义一个字节串形式的flag:b'flag{}'
    • Crypto库导入AES加密模块。
    • hashlib库导入sha256哈希函数。
    • 导入随机数生成模块random
  2. 定义一些变量

    • n是一个大整数。
    • m是一个整数。
    • M是一个256位的随机素数。
    • As是一个包含n个在0到M之间的随机数的列表。
    • xs是一个包含n个随机向量的列表,每个向量有m个元素。
    • BsAsxs的线性组合。
  3. 生成IV

    • 使用sha256哈希函数对sum(As)进行哈希,取前16字节作为IV。
  4. 创建AES加密对象并加密flag

    • 使用CBC模式和生成的IV创建AES加密对象。
    • 使用AES加密flag,并进行填充。
  5. 打印加密后的密文、Bs和M

    • 打印加密后的密文。
    • 打印Bs的值。
    • 打印M的值。
  6. 获取加密后的密文

    • 从打印的输出中获取加密后的密文。
  7. 获取IV

    • IV是通过sha256(str(int(sum(As))).encode()).digest()[:16]生成的。
    • 需要知道As的值来计算IV。
  8. 获取CBC_key

    • 需要知道CBC_key的值来进行解密。
  9. 解密密文

    • 使用AES解密对象和IV来解密密文。
  10. 解密密文

    • 使用AES解密对象和IV来解密密文。
    • 我们已经获取了加密后的密文、IV和CBC_key,我们可以进行以下步骤来解密flag:
  1. from Crypto.Cipher import AES
  2. from Crypto.Util.Padding import unpad
  3. # 假设我们已经获取了加密后的密文、IV和CBC_key
  4. cipher = b'encrypted_cipher_text' # 替换为实际的加密后的密文
  5. IV = b'generated_IV_here' # 替换为实际的IV
  6. CBC_key = b'CBC_key_here' # 替换为实际的CBC_key
  7. # 创建AES解密对象
  8. aes = AES.new(CBC_key, AES.MODE_CBC, iv=IV)
  9. # 解密密文
  10. decrypted_padded_flag = aes.decrypt(cipher)
  11. # 去除填充
  12. flag = unpad(decrypted_padded_flag, 16)
  13. print(flag)

CopyInsert

请确保替换cipherIVCBC_key为实际的值。这样,我们就可以解密并打印出flag。

脚本如下

  1. from Crypto.Util.number import * # 导入Crypto库中的实用函数
  2. from Crypto.Cipher import AES # 导入AES加密模块
  3. from hashlib import sha256 # 导入SHA-256哈希函数
  4. import random # 导入随机数生成模块
  5. from gmpy2 import * # 导入gmpy2库,用于大数运算
  6. # 已知参数
  7. n = 104765768221225848380273603921218042896496091723683489832860494733817042387427987244507704052637674086899990536096984680534816330245712225302233334574349506189442333792630084535988347790345154447062755551340749218034086168589615547612330724516560147636445207363257849894676399157463355106007051823518400959497 # RSA模数n
  8. h = 7203581190271819534576999256270240265858103390821370416379729376339409213191307296184376071456158994788217095325108037303267364174843305521536186849697944281211331950784736288318928189952361923036335642517461830877284034872063160219932835448208223363251605926402262620849157639653619475171619832019229733872640947057355464330411604345531944267500361035919621717525840267577958327357608976854255222991975382510311241178822169596614192650544883130279553265361702184320269130307457859444687753108345652674084307125199795884106515943296997989031669214605935426245922567625294388093837315021593478776527614942368270286385 # 提示值h
  9. c = 86362463246536854074326339688321361763048758911466531912202673672708237653371439192187048224837915338789792530365728395528053853409289475258767985600884209642922711705487919620655525967504514849941809227844374505134264182900183853244590113062802667305254224702526621210482746686566770681208335492189720633162 # RSA密文c
  10. q = 11846999515401139806618780458482772585816656222161925595380112630854263318903047176862162285755281915011589524788709945023820217521669415569797208065004797 # 素数q
  11. p = n // q # 计算素数p
  12. # 计算phi和d
  13. phi = (p - 1) * (q - 1) # 计算欧拉函数phi(n)
  14. d = inverse(65537, phi) # 计算RSA私钥d,即65537在模phi下的逆元
  15. # 解密c得到m
  16. m = pow(c, d, n) # 使用私钥d解密密文c
  17. print(long_to_bytes(m)) # 将解密得到的整数m转换为字节并打印
  18. # AES解密
  19. CBC_key = b'mylove_in_summer' # AES解密密钥
  20. enc = b'%\x97\xf77\x16.\x83\x99\x06^\xf2h!k\xfaN6\xb0\x19vd]\x04B\x9e&\xc1V\xed\xa3\x08gX\xb2\xe3\x16\xc2y\xf5/\xb1\x1f>\xa1\xa0DO\xc6gy\xf2l\x1e\xe89\xaeU\xf7\x9d\x03\xe5\xcd*{' # AES加密的密文
  21. sum = 1190342683523422755570459424048363591795982274808192123460316142044766104571627 # 用于生成IV的值
  22. IV = sha256(str(sum).encode()).digest()[:16] # 使用SHA-256哈希函数生成IV
  23. aes = AES.new(CBC_key, AES.MODE_CBC, iv=IV) # 创建AES CBC模式的解密对象
  24. cipher = aes.decrypt(enc) # 解密AES密文
  25. print(cipher) # 打印解密后的明文

视频讲解 :

2024春秋竞赛happy2024视频解析

flag

Signature

原题代码

  1. import os
  2. import hashlib
  3. from Crypto.Util.number import *
  4. from Crypto.PublicKey import DSA
  5. import random
  6. def gen_proof_key():
  7. # 定义一个固定的密码字符串
  8. password = 'happy_the_year_of_loong'
  9. getin = '' #定义一个空字符串变量
  10. # 随机将密码字符串中的字符转换为大写或小写
  11. for i in password:#password 字符串中的每个字符进行循环。
  12. if random.randint(0, 1):#生成一个随机整数,如果该整数为 1,则执行下一行代码。
  13. getin += i.lower()#将当前字符转换为小写并添加到 getin 字符串中。
  14. else:
  15. getin += i.upper()#将当前字符转换为大写并添加到 getin 字符串中
  16. # 计算转换后字符串的SHA-256哈希值
  17. ans = hashlib.sha256(getin.encode()).hexdigest()#字符串的 SHA-256 哈希值,并将结果存储在 ans 变量中。
  18. return getin, ans#返回包含转换后的字符串 getin 和其 SHA-256 哈希值 ans 的元组。
  19. def gen_key():
  20. # 生成一个私钥,范围在2到q-2之间
  21. pri = random.randint(2, q - 2)
  22. # 计算公钥,使用离散对数问题
  23. pub = pow(g, pri, p)#使用离散对数问题计算公钥 pub,即 g 的 pri 次方模 p。
  24. return pri, pub#返回包含私钥 pri 和公钥 pub 的元组。
  25. def sign(m, pri):
  26. k = int(hashlib.md5(os.urandom(20)).hexdigest(), 16) # 生成一个随机的k值,用于签名过程
  27. H = int(hashlib.sha256(m).hexdigest(), 16) # 计算消息的SHA-256哈希值
  28. r = pow(g, k, p) % q# 计算签名中的r值
  29. s = pow(k, -1, q) * (H + pri * r) % q# 计算签名中的s值
  30. return r, s
  31. def verify(pub, m, signature):
  32. r, s = signature # 从签名中提取r和s
  33. if r <= 0 or r >= q or s <= 0 or s >= q: # 如果r或s不在有效范围内,返回False
  34. return False
  35. w = pow(s, -1, q) # 计算s的模逆w,w * s ≡ 1 (mod q)
  36. H = int(hashlib.sha256(m).hexdigest(), 16) # 计算消息m的SHA-256哈希值,并转换为整数
  37. # 计算u1和u2
  38. u1 = H * w % q
  39. u2 = r * w % q
  40. # 计算v值
  41. v = (pow(g, u1, p) * pow(pub, u2, p) % p) % q # 计算v = (g^u1 * pub^u2 mod p) mod q
  42. # 验证签名是否正确
  43. return v == r # 如果v等于r,则签名正确,返回True;否则返回False
  44. def login():
  45. print('Hello sir, Plz login first')# 打印欢迎信息
  46. # 定义菜单选项
  47. menu = '''
  48. 1. sign
  49. 2. verify
  50. 3. get my key
  51. '''
  52. times = 8# 初始化尝试次数
  53. while True:# 进入循环
  54. print(menu)# 打印菜单
  55. if times < 0: # 检查尝试次数是否用完
  56. print('Timeout!')# 检查尝试次数是否用完
  57. return False
  58. choice = int(input('>'))# 获取用户选择
  59. if choice == 1:# 处理用户选择
  60. name = input('Username:').encode()# 获取用户名并编码为字节
  61. if b'admin' in name:# 检查用户名是否包含'admin'
  62. print('Get out!') # 打印拒绝信息并返回False
  63. return False
  64. r, s = sign(name, pri)# 签名用户名
  65. print(f'This is your signature -- > {r},{s}') # 打印签名结果
  66. times -= 1 # 减少尝试次数
  67. elif choice == 2:# 处理用户选择
  68. print('Sure, Plz input your signature') # 提示用户输入签名
  69. r = int(input('r:'))# 获取签名参数r
  70. s = int(input('s:'))# 获取签名参数s
  71. if verify(pub, b'admin', (r, s)) == True:# 验证签名
  72. print('login success!')
  73. return True# 打印登录成功信息并返回True
  74. else:
  75. print('you are not admin')# 打印登录失败信息并返回False
  76. return False
  77. elif choice == 3:# 处理用户选择
  78. # 打印密钥信息
  79. print(f'Oh, your key is {(p, q, g)}')
  80. getin, ans = gen_proof_key() # 调用函数生成一个随机的字符串及其哈希值
  81. print(f'Your gift --> {ans[:6]}') # 打印哈希值的前6个字符作为礼物
  82. your_token = input('Plz input your token\n>') # 提示用户输入token
  83. if your_token != getin: # 检查用户输入的token是否与生成的字符串匹配
  84. print('Get out!') # 如果不匹配,打印拒绝信息
  85. exit(0) # 退出程序
  86. key = DSA.generate(1024)# 生成DSA密钥对、
  87. p, q, g = key.p, key.q, key.g# 获取DSA参数
  88. pri, pub = gen_key()pri, pub = key.key# 获取私钥和公钥
  89. if login() == False:# 进行登录过程
  90. exit(0)
  91. print(open('/flag', 'r').read())# 如果登录成功,读取并显示flag文件内容
  92. '''

解题思路

生成正确的 token:
运行 gen_proof_key 函数,获取 getin 和 ans。
使用 getin 作为 token 输入。
获取 DSA 密钥对:
生成 DSA 密钥对,获取 p, q, g, pri, pub。
通过 login 函数的验证:
选择选项 1 签名一个非 admin 的用户名,获取签名 (r, s)。
选择选项 3 获取 (p, q, g)。
使用获取的 (p, q, g) 和签名 (r, s) 来伪造一个 admin 的签名。
伪造 admin 的签名:
由于 k 是随机生成的,且 k 的值可以通过 r 和 s 推导出来(如果 k 被重用),可以尝试重用 k 来伪造 admin 的签名。
由于 k 是随机生成的,且 k 的值可以通过 r 和 s 推导出来(如果 k 被重用),你可以尝试重用 k 来伪造 admin 的签名。
计算 k:
     k = (H + pri * r) * inverse(s, q) % q
CopyInsert
使用 k 计算 admin 的签名:
    H_admin = int(hashlib.sha256(b'admin').hexdigest(), 16)
    r_admin = pow(g, k, p) % q
     s_admin = inverse(k, q) * (H_admin + pri * r_admin) % q
CopyInsert
验证 admin 的签名:
选择选项 2,输入伪造的 admin 的签名 (r_admin, s_admin)。
如果验证通过,将成功登录为 admin,并获得 flag。

参考博客

因为我用的是虚拟机 ,题目有容器使用没办法直接做,所以你们可以参考一下这个博主

2024春秋杯网络安全联赛夏季赛Crypto-CSDN博客

  1. import os
  2. import hashlib
  3. from Crypto.Util.number import *
  4. from Crypto.PublicKey import DSA
  5. import random
  6. def gen_proof_key():
  7. # 定义一个固定的密码字符串
  8. password = 'happy_the_year_of_loong'
  9. getin = '' #定义一个空字符串变量
  10. # 随机将密码字符串中的字符转换为大写或小写
  11. for i in password:#password 字符串中的每个字符进行循环。
  12. if random.randint(0, 1):#生成一个随机整数,如果该整数为 1,则执行下一行代码。
  13. getin += i.lower()#将当前字符转换为小写并添加到 getin 字符串中。
  14. else:
  15. getin += i.upper()#将当前字符转换为大写并添加到 getin 字符串中
  16. # 计算转换后字符串的SHA-256哈希值
  17. ans = hashlib.sha256(getin.encode()).hexdigest()#字符串的 SHA-256 哈希值,并将结果存储在 ans 变量中。
  18. return getin, ans#返回包含转换后的字符串 getin 和其 SHA-256 哈希值 ans 的元组。
  19. def gen_key():
  20. # 生成一个私钥,范围在2到q-2之间
  21. pri = random.randint(2, q - 2)
  22. # 计算公钥,使用离散对数问题
  23. pub = pow(g, pri, p)#使用离散对数问题计算公钥 pub,即 g 的 pri 次方模 p。
  24. return pri, pub#返回包含私钥 pri 和公钥 pub 的元组。
  25. def sign(m, pri):
  26. k = int(hashlib.md5(os.urandom(20)).hexdigest(), 16) # 生成一个随机的k值,用于签名过程
  27. H = int(hashlib.sha256(m).hexdigest(), 16) # 计算消息的SHA-256哈希值
  28. r = pow(g, k, p) % q# 计算签名中的r值
  29. s = pow(k, -1, q) * (H + pri * r) % q# 计算签名中的s值
  30. return r, s
  31. def verify(pub, m, signature):
  32. r, s = signature # 从签名中提取r和s
  33. if r <= 0 or r >= q or s <= 0 or s >= q: # 如果r或s不在有效范围内,返回False
  34. return False
  35. w = pow(s, -1, q) # 计算s的模逆w,w * s ≡ 1 (mod q)
  36. H = int(hashlib.sha256(m).hexdigest(), 16) # 计算消息m的SHA-256哈希值,并转换为整数
  37. # 计算u1和u2
  38. u1 = H * w % q
  39. u2 = r * w % q
  40. # 计算v值
  41. v = (pow(g, u1, p) * pow(pub, u2, p) % p) % q # 计算v = (g^u1 * pub^u2 mod p) mod q
  42. # 验证签名是否正确
  43. return v == r # 如果v等于r,则签名正确,返回True;否则返回False
  44. def login():
  45. print('Hello sir, Plz login first')# 打印欢迎信息
  46. # 定义菜单选项
  47. menu = '''
  48. 1. sign
  49. 2. verify
  50. 3. get my key
  51. '''
  52. times = 8# 初始化尝试次数
  53. while True:# 进入循环
  54. print(menu)# 打印菜单
  55. if times < 0: # 检查尝试次数是否用完
  56. print('Timeout!')# 检查尝试次数是否用完
  57. return False
  58. choice = int(input('>'))# 获取用户选择
  59. if choice == 1:# 处理用户选择
  60. name = input('Username:').encode()# 获取用户名并编码为字节
  61. if b'admin' in name:# 检查用户名是否包含'admin'
  62. print('Get out!') # 打印拒绝信息并返回False
  63. return False
  64. r, s = sign(name, pri)# 签名用户名
  65. print(f'This is your signature -- > {r},{s}') # 打印签名结果
  66. times -= 1 # 减少尝试次数
  67. elif choice == 2:# 处理用户选择
  68. print('Sure, Plz input your signature') # 提示用户输入签名
  69. r = int(input('r:'))# 获取签名参数r
  70. s = int(input('s:'))# 获取签名参数s
  71. if verify(pub, b'admin', (r, s)) == True:# 验证签名
  72. print('login success!')
  73. return True# 打印登录成功信息并返回True
  74. else:
  75. print('you are not admin')# 打印登录失败信息并返回False
  76. return False
  77. elif choice == 3:# 处理用户选择
  78. # 打印密钥信息
  79. print(f'Oh, your key is {(p, q, g)}')
  80. getin, ans = gen_proof_key() # 调用函数生成一个随机的字符串及其哈希值
  81. print(f'Your gift --> {ans[:6]}') # 打印哈希值的前6个字符作为礼物
  82. your_token = input('Plz input your token\n>') # 提示用户输入token
  83. if your_token != getin: # 检查用户输入的token是否与生成的字符串匹配
  84. print('Get out!') # 如果不匹配,打印拒绝信息
  85. exit(0) # 退出程序
  86. key = DSA.generate(1024)# 生成DSA密钥对、
  87. p, q, g = key.p, key.q, key.g# 获取DSA参数
  88. pri, pub = gen_key()pri, pub = key.key# 获取私钥和公钥
  89. if login() == False:# 进行登录过程
  90. exit(0)
  91. print(open('/flag', 'r').read())# 如果登录成功,读取并显示flag文件内容
  92. '''

代码实现了一个基于DSA(数字签名算法)的登录系统。主要功能和流程:

生成证明密钥 (gen_proof_key):

生成一个随机的字符串 getin,它是固定密码字符串 'happy_the_year_of_loong' 的随机大小写混合版本。
计算 getin 的 SHA-256 哈希值 ans。
返回 getin 和 ans。
生成密钥对 (gen_key):

生成一个私钥 pri,它是介于 2 和 q - 2 之间的随机整数。
计算公钥 pub,它是 g 的 pri 次方模 p。
返回 pri 和 pub。
签名 (sign):

生成一个随机数 k,它是 20 字节随机数据的 MD5 哈希值的整数表示。
计算消息 m 的 SHA-256 哈希值 H。
计算签名参数 r 和 s。
返回 r 和 s。
验证 (verify):

检查签名参数 r 和 s 是否在有效范围内。
计算 w,它是 s 的模逆。
计算消息 m 的 SHA-256 哈希值 H。
计算 u1 和 u2。
计算 v,它是 g 的 u1 次方和 pub 的 u2 次方模 p 的结果再模 q。
返回 v 是否等于 r。
登录 (login):

提供一个菜单,允许用户选择签名、验证或获取密钥。
用户可以选择签名一个非 admin 的用户名,获取签名 (r, s)。
用户可以选择验证 admin 的签名 (r, s)。
用户可以选择获取密钥 (p, q, g)。
如果验证通过,用户将成功登录为 admin,并获得 flag。
主流程:
生成证明密钥 getin 和 ans。
提示用户输入 token,如果 token 不匹配 getin,则退出。
生成 DSA 密钥对 (p, q, g) 和 (pri, pub)。
调用 login 函数进行登录。
如果登录成功,打印 /flag 文件的内容。
这个系统的主要目的是通过 DSA 签名和验证机制来模拟一个安全的登录过程,确保只有拥有正确签名的人才能以 admin 身份登录并获取 flag

 视频讲解 :

2024春秋竞赛夏季赛Signature解题思路

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/890378
推荐阅读
相关标签
  

闽ICP备14008679号