Crypto学习笔记

Crypto学习笔记(持续更新)

数学是个看天赋的学科,而我恰好没有这个天赋,别人很容易理解的内容,我需要学习很久。

本篇博客将记录我探索Crypto世界的点滴旅程,初衷是为了方便自己查阅,也便于自我成长与回顾,倘若笔者浅薄之见,能有幸为诸位师傅学问之海添一滴水,实乃蓬荜生辉,甚为喜悦。在此过程中,各位师傅如有任何观察到的疏漏或偏差,欢迎随时指正,先谢过各位师傅了。

二零二四年四月三十日记

2024第九届中国海洋大学信息安全竞赛-NeXT RSA(费马分解法,p、q相近)

题目描述:聪明的小军觉得既然都选择了随机的 p,那根据 p 选择 q,q 也是随机的辣!

import sympy
import libnum

flag="flag{" + "???" + "}"
m = libnum.s2n(flag)

p = sympy.randprime(1<<1024, 1<<1025)# 生成1024位到1025位之间的随机素数p
q = sympy.nextprime(p)# 找到大于p的下一个素数q

n = p*q
r = (p-1)*(q-1)
e = 65537

c = pow(m, e, n)

print(n, e, c)
# output:
#80044118049755180996754407858488943779355738585718372337839486032339412481191013051614126608584578841408197524632831442032118319629160505851518198448787590483634506563248531254421862061651099856312546562506221294620627871718678484548245902274972044599314097339549053518589561289734819710218838311181044519738709148493164321955860982700783886286661558574861608455547990794798848491695189544811325833194530596317989718866319530140199263278168146224240677087191093183415595617994125075880280632369616506148501757653260154487000183157405531772172082897743929126980157956142627803176227942226654177011633301413616266656761
#65537
#23280133104463252598665779150831148192014617461904564929071121215373331248942762386170411274023248423328388793808975632652896384007449549469345318875514363621903138122407682293848670093433946555776164835208375667498606187869211466397624286383057425296636315379314349307816391315242971306898487494604324473266965665471735612154916305882443496151118031672777088597821127499085632141307413890900246444539517971766135909771880642211582699957211983212981047822362311969553832913399476190919026666192056319334425636757404603336130688707109219644178606626422717046059209499394056295682594928581470210114322505904198054215544

其中 q 是 p 的下一个素数,这题可以使用费马分解法。

由于p,q直接相邻,则必有p < sqrt(n) < q 且p,q都是紧挨着sqrt(n) 的素数,用题目里的nextprime(sqrt(n)) 即可得q,进而解出密文。

解题脚本:

import gmpy2
import sympy
from Crypto.Util.number import *
 
n = 80044118049755180996754407858488943779355738585718372337839486032339412481191013051614126608584578841408197524632831442032118319629160505851518198448787590483634506563248531254421862061651099856312546562506221294620627871718678484548245902274972044599314097339549053518589561289734819710218838311181044519738709148493164321955860982700783886286661558574861608455547990794798848491695189544811325833194530596317989718866319530140199263278168146224240677087191093183415595617994125075880280632369616506148501757653260154487000183157405531772172082897743929126980157956142627803176227942226654177011633301413616266656761
c = 23280133104463252598665779150831148192014617461904564929071121215373331248942762386170411274023248423328388793808975632652896384007449549469345318875514363621903138122407682293848670093433946555776164835208375667498606187869211466397624286383057425296636315379314349307816391315242971306898487494604324473266965665471735612154916305882443496151118031672777088597821127499085632141307413890900246444539517971766135909771880642211582699957211983212981047822362311969553832913399476190919026666192056319334425636757404603336130688707109219644178606626422717046059209499394056295682594928581470210114322505904198054215544
e = 65537
n2=gmpy2.iroot(n,2)[0]
p=sympy.nextprime(n2)
q=n//p
phi=(p-1)*(q-1)
d=gmpy2.invert(e,phi)
m=pow(c,d,n)
print(long_to_bytes(m))

这段代码使用了几个Python库(gmpy2, sympy, Crypto.Util.number)来执行一个RSA加密信息的解密过程。

  1. 导入所需库:

    import gmpy2
    import sympy
    from Crypto.Util.number import *
    
    • gmpy2库用于高效的数学运算,特别是大数运算。
    • sympy库用于符号数学计算,这里主要用到了寻找下一个素数的功能。
    • Crypto.Util.number模块包含了处理大整数的工具。
  2. 定义密文、模数和公钥指数:

    n = ...  # 很长的整数,模数
    c = ...  # 密文
    e = 65537  # 公钥指数,常见的RSA公钥指数
    
  3. 计算n的平方根:

    n2=gmpy2.iroot(n,2)[0]
    

    这里尝试计算n的平方根,并取整数部分,用于后续步骤中的近似估计p或q的大小。

  4. 寻找p和q:

    p=sympy.nextprime(n2)
    q=n//p
    

    首先,使用sympy.nextprime(n2)找到大于n的平方根的下一个素数作为p的一个估计值。然后,通过n除以p得到q的近似值。这里的方法假设n是两个相近的素数的乘积,且通过近似方法找到这两个素数。

  5. 计算欧拉函数φ(n):

    phi=(p-1)*(q-1)
    

    计算模数n对应的欧拉函数φ(n),用于计算解密指数d。

  6. 计算解密指数d:

    d=gmpy2.invert(e,phi)
    

    利用扩展欧几里得算法计算d,使得(ed \equiv 1 \mod \phi(n))。

  7. 解密密文:

    m=pow(c,d,n)
    

    使用快速幂算法计算(c^d \mod n),得到原始明文的数值表示。

  8. 转换并打印解密结果:

    print(long_to_bytes(m))
    

    将解密得到的数值转换为字节串并打印出来,通常用于展示解密后的文本信息。

2024第九届中国海洋大学信息安全竞赛-Base64*rot13

题目描述:MzkuM3gyrzI6Z3cyrzHlMKcSra0=

题目名字提示比较明显了,经过base64和rot13的,这里经过测试是先rot13加密后base64加密的,rot13其实就是凯撒的一种变种,它是将字母表中的每个字母替换成字母表中固定位置偏移13个位置的字母,其它非字母的字符保持不变。虽然有很多在线解码脚本,但是我还是用ai写出了解密脚本,方便自己将来在离线环境中仍能做题。

解题脚本:

import base64

def rot13_decode(text):
    """
    对给定的文本执行ROT13解码。
    """
    result = []
    for char in text:
        ascii_code = ord(char)
        if 'A' <= char <= 'Z':
            result.append(chr(((ascii_code - 65 + 13) % 26) + 65))
        elif 'a' <= char <= 'z':
            result.append(chr(((ascii_code - 97 + 13) % 26) + 97))
        else:
            result.append(char)
    return ''.join(result)

def base64_decode(text):
    """
    对给定的Base64编码的文本执行解码,并假设解码后内容为UTF-8编码。
    """
    try:
        base64_decoded_bytes = base64.b64decode(text)
        return base64_decoded_bytes.decode('utf-8')
    except base64.binascii.Error:
        # 如果解码失败,这里可以选择抛出异常或返回某个默认值
        raise ValueError("Invalid Base64 input.")

encoded_text = "MzkuM3gyrzI6Z3cyrzHlMKcSra0="
rot13_decoded_text = rot13_decode(encoded_text)
print("After ROT13 decoding:", rot13_decoded_text)
final_decoded_text = base64_decode(rot13_decoded_text)
print("After Base64 decoding:", final_decoded_text)

2024第九届中国海洋大学信息安全竞赛-模!

题目表述:

from math import factorial
from functools import reduce

flag = "flag{xxxxxxxxx}"

def mooooo(s: str):
    res = 0
    for i in s:
        res <<= 8
        res += ( factorial(ord(i)) % 233 )
    return res

table = "abcdefghijklmnopqrstuvwxyz{}"
assert(reduce(lambda p,i:(i in table)*p, flag, True))

print(mooooo(flag))
# output: 2508450541438803643416583335895451914701844680466330955847

导入模块

from math import factorial
from functools import reduce
  • factorial 函数来自 math 模块,用于计算一个数的阶乘(即从1乘到该数的所有正整数的乘积)。
  • reduce 函数来自 functools 模块,它对一个序列中的元素累积应用二元函数,从左到右,因此通常需要一个初始值。

定义变量

flag = "flag{xxxxxxxxx}"

这是一个字符串变量,表示待处理的“flag”。其中"xxxxxxxxx"代表未知的具体内容,通常在CTF(Capture The Flag)等信息安全竞赛中用于存储需要解密或解析的秘密信息。

定义函数 mooooo

def mooooo(s: str):
    res = 0
    for i in s:
        res <<= 8
        res += (factorial(ord(i)) % 233)  # 计算字符的阶乘后对233取模,累加到结果中
    return res

此函数接收一个字符串s作为参数,遍历字符串中的每一个字符。对于每个字符,它先将当前结果左移8位(等效于乘以256),然后加上该字符的ASCII码对应的阶乘值对233取模的结果。最后返回累加计算的总结果。

断言

table = "abcdefghijklmnopqrstuvwxyz{}"
assert(reduce(lambda p,i:(i in table)*p, flag, True))

这里定义了一个字符串table,包含了小写字母、大括号。接下来的assert语句用于检查flag中的每个字符是否都在table定义的字符集中。reduce函数配合一个lambda表达式,累积判断flag中每个字符是否属于table,若所有字符都在table内,则累积结果为True,否则为False。如果最终结果为False,程序会抛出AssertionError异常。


题目脚本中对 flag 的每个字节的值都先进行了阶乘再模 233,结果也是一个字节一个字节地存放,其中flag 每个字节的值都不会超过 233 且 233 是个素数,所以结果中的每个字节的值都能唯一对应上 table中的一个字符,逐位爆破即可。

解密脚本:

from math import factorial  
  
# 已知的输出值  
output = 2508450541438803643416583335895451914701844680466330955847  
  
# 逆向mooooo函数的逻辑  
def inverse_mooooo(output):  
    s = ""  
    while output > 0:  
        # 从output中获取最右侧的8位  
        char_val = output & 0xFF  
          
        # 查找对应的字符,通过遍历所有可能的字符并计算其阶乘对233取模  
        for char in "abcdefghijklmnopqrstuvwxyz{}":  
            if (factorial(ord(char)) % 233) == char_val:  
                s = char + s  # 将找到的字符添加到结果字符串的前面  
                break  
        # 左移8位以处理下一个字符  
        output >>= 8  
    return s  
  
# 使用inverse_mooooo函数尝试恢复flag  
flag = inverse_mooooo(output)  
print(flag)  # 输出应该是原始的flag字符串
posted @   山西小嫦娥  阅读(51)  评论(0编辑  收藏  举报
努力加载评论中...
点击右上角即可分享
微信分享提示