Crypto
Very Smooth
描述
Forget safe primes… Here, we like to live life dangerously… >:)
gen.py
#!/usr/bin/python
from binascii import hexlify
from gmpy2 import *
import math
import os
import sys
if sys.version_info < (3, 9):
    math.gcd = gcd
    math.lcm = lcm
_DEBUG = False
FLAG  = open('flag.txt').read().strip()
FLAG  = mpz(hexlify(FLAG.encode()), 16)
SEED  = mpz(hexlify(os.urandom(32)).decode(), 16)
STATE = random_state(SEED)
def get_prime(state, bits):
    return next_prime(mpz_urandomb(state, bits) | (1 << (bits - 1)))
def get_smooth_prime(state, bits, smoothness=16):
    p = mpz(2)
    p_factors = [p]
    while p.bit_length() < bits - 2 * smoothness:
        factor = get_prime(state, smoothness)
        p_factors.append(factor)
        p *= factor
    bitcnt = (bits - p.bit_length()) // 2
    while True:
        prime1 = get_prime(state, bitcnt)
        prime2 = get_prime(state, bitcnt)
        tmpp = p * prime1 * prime2
        if tmpp.bit_length() < bits:
            bitcnt += 1
            continue
        if tmpp.bit_length() > bits:
            bitcnt -= 1
            continue
        if is_prime(tmpp + 1):
            p_factors.append(prime1)
            p_factors.append(prime2)
            p = tmpp + 1
            break
    p_factors.sort()
    return (p, p_factors)
e = 0x10001
while True:
    p, p_factors = get_smooth_prime(STATE, 1024, 16)
    if len(p_factors) != len(set(p_factors)):
        continue
    # Smoothness should be different or some might encounter issues.
    q, q_factors = get_smooth_prime(STATE, 1024, 17)
    if len(q_factors) != len(set(q_factors)):
        continue
    factors = p_factors + q_factors
    if e not in factors:
        break
if _DEBUG:
    import sys
    sys.stderr.write(f'p = {p.digits(16)}\n\n')
    sys.stderr.write(f'p_factors = [\n')
    for factor in p_factors:
        sys.stderr.write(f'    {factor.digits(16)},\n')
    sys.stderr.write(f']\n\n')
    sys.stderr.write(f'q = {q.digits(16)}\n\n')
    sys.stderr.write(f'q_factors = [\n')
    for factor in q_factors:
        sys.stderr.write(f'    {factor.digits(16)},\n')
    sys.stderr.write(f']\n\n')
n = p * q
m = math.lcm(p - 1, q - 1)
d = pow(e, -1, m)
c = pow(FLAG, e, n)
print(f'n = {n.digits(16)}')
print(f'c = {c.digits(16)}')
 
output.txt
n = e77c4035292375af4c45536b3b35c201daa5db099f90af0e87fedc480450873715cffd53fc8fe5db9ac9960867bd9881e2f0931ffe0cea4399b26107cc6d8d36ab1564c8b95775487100310f11c13c85234709644a1d8616768abe46a8909c932bc548e23c70ffc0091e2ed9a120fe549583b74d7263d94629346051154dad56f2693ad6e101be0e9644a84467121dab1b204dbf21fa39c9bd8583af4e5b7ebd9e02c862c43a426e0750242c30547be70115337ce86990f891f2ad3228feea9e3dcd1266950fa8861411981ce2eebb2901e428cfe81e87e415758bf245f66002c61060b2e1860382b2e6b5d7af0b4a350f0920e6d514eb9eac7f24a933c64a89
c = 671028df2e2d255962dd8685d711e815cbea334115c30ea2005cf193a1b972e275c163de8cfb3d0145a453fec0b837802244ccde0faf832dc3422f56d6a384fbcb3bfd969188d6cd4e1ca5b8bc48beca966f309f52ff3fc3153cccaec90d8477fd24dfedc3d4ae492769a6afefbbf50108594f18963ab06ba82e955cafc54a978dd08971c6bf735b347ac92e50fe8e209c65f946f96bd0f0c909f34e90d67a4d12ebe61743b438ccdbcfdf3a566071ea495daf77e7650f73a7f4509b64b9af2dd8a9e33b6bd863b889a69f903ffef425ea52ba1a293645cbac48875c42220ec0b37051ecc91daaf492abe0aaaf561ffb0c2b093dcdabd7863b1929f0411891f5
 
分析
要点在于在rsa中使用了sooth prime(光滑数)+ 1形式的素数作为n的两个素因子。
光滑数
 光滑数(Smooth Number)指可以分解为小素数乘积的正整数。
 题目中的
    
     
      
       
        p
       
      
      
       p
      
     
    p由许多小质数乘积+1得出,故
    
     
      
       
        p
       
       
        −
       
       
        1
       
      
      
       p-1
      
     
    p−1 则为许多小质数的乘积,即
    
     
      
       
        p
       
       
        −
       
       
        1
       
      
      
       p-1
      
     
    p−1 是光滑数。
Pollard’s p − 1 算法
 当 
    
     
      
       
        p
       
      
      
       p
      
     
    p 是 
    
     
      
       
        N
       
      
      
       N
      
     
    N 的因数,并且 
    
     
      
       
        p
       
       
        −
       
       
        1
       
      
      
       p-1
      
     
    p−1 是光滑数,可能可以使用 Pollard’s p − 1 算法来分解 
    
     
      
       
        N
       
      
      
       N
      
     
    N 。
 首先根据费马小定理:
 如果
    
     
      
       
        p
       
      
      
       p
      
     
    p 是一个质数,而整数 
    
     
      
       
        a
       
      
      
       a
      
     
    a 不是 
    
     
      
       
        p
       
      
      
       p
      
     
    p 的倍数,则有
    
     
      
       
        
         a
        
        
         
          p
         
         
          −
         
         
          1
         
        
       
       
        ≡
       
       
        1
        
       
        m
       
       
        o
       
       
        d
        
       
        p
       
      
      
       a^{p−1}\equiv1\,mod\,p
      
     
    ap−1≡1modp
则
 
     
      
       
        
         
          a
         
         
          
           p
          
          
           −
          
          
           1
          
         
        
        
         ≡
        
        
         
          1
         
         
          t
         
        
        
         ≡
        
        
         1
         
        
         m
        
        
         o
        
        
         d
         
        
         p
        
       
       
         a^{p-1}\equiv1^t\equiv 1\,mod\,p 
       
      
     ap−1≡1t≡1modp
 可改为等式:
 
     
      
       
        
         
          a
         
         
          
           t
          
          
           (
          
          
           p
          
          
           −
          
          
           1
          
          
           )
          
         
        
        
         −
        
        
         1
        
        
         =
        
        
         k
        
        
         ∗
        
        
         p
        
       
       
         a^{t(p-1)}-1=k*p 
       
      
     at(p−1)−1=k∗p
 即$ a^{t(p-1)} - 1$ 是 
    
     
      
       
        p
       
      
      
       p
      
     
    p的倍数 。
 然后根据 Pollard’s p - 1 算法:
如果 p − 1 p − 1 p−1是一些很小质数的乘积,那么$ n! 就 能 被 就能被 就能被p−1$ 整除。即 n ! = t ( p − 1 ) n!=t(p-1) n!=t(p−1)。
对于每一个$ n = 2 , 3 , 4 , . . . $任意选择一个底数 
    
     
      
       
        a
       
      
      
       a
      
     
    a(事实上,可以简单地选择为 2),并计算:
 
     
      
       
        
         g
        
        
         c
        
        
         d
        
        
         (
        
        
         
          a
         
         
          
           n
          
          
           !
          
         
        
        
         −
        
        
         1
        
        
         ,
        
        
         N
        
        
         )
        
       
       
         gcd(a^{n!}-1,N) 
       
      
     gcd(an!−1,N)
 如果结果不为 1 或 
    
     
      
       
        N
       
      
      
       N
      
     
    N,那么就已成功分解 
    
     
      
       
        N
       
      
      
       N
      
     
    N。
但当 
    
     
      
       
        n
       
      
      
       n
      
     
    n较大时,直接计算 
    
     
      
       
        n
       
       
        !
       
      
      
       n!
      
     
    n! 将会很消耗资源。在遍历
    
     
      
       
        n
       
      
      
       n
      
     
    n 时,可以简化运算。
 因为:
 
     
      
       
        
         
          a
         
         
          
           n
          
          
           !
          
         
         
        
          
        
        
         m
        
        
         o
        
        
         d
         
        
          
        
        
         N
        
        
         =
        
        
         (
        
        
         a
         
        
          
        
        
         m
        
        
         o
        
        
         d
        
        
          
         
        
         N
        
        
         
          )
         
         
          
           n
          
          
           !
          
         
         
        
         m
        
        
         o
        
        
         d
         
        
         N
        
       
       
         a^{n!}\, mod\,  N=(a\, mod \,N)^{n!}\,mod\,N 
       
      
     an! mod N=(a mod N)n!modN
 所以:
 
     
      
       
        
         
          a
         
         
          
           n
          
          
           !
          
         
         
        
         m
        
        
         o
        
        
         d
         
        
         N
        
        
         =
        
        
         
          {
         
         
          
           
            
             
              
               (
              
              
               a
               
              
               m
              
              
               o
              
              
               d
               
              
               N
              
              
               
                )
               
               
                2
               
               
              
               m
              
              
               o
              
              
               d
               
              
               N
              
              
              
               n
              
              
               =
              
              
               2
              
             
            
           
          
          
           
            
             
              
               (
              
              
               
                a
               
               
                
                 (
                
                
                 n
                
                
                 −
                
                
                 1
                
                
                 )
                
                
                 !
                
               
               
              
               m
              
              
               o
              
              
               d
               
              
               N
              
              
               
                )
               
               
                n
               
               
              
               m
              
              
               o
              
              
               d
               
              
               N
              
              
              
               n
              
              
               ≥
              
              
               3
              
             
            
           
          
         
        
       
       
         a^{n!}\,mod\,N=\left\{ \begin{aligned} (a\,mod\,N)^2\,mod\,N\quad n=2\\ (a^{(n-1)!}\,mod\,N)^n\,mod\,N\quad n\geq3\\ \end{aligned} \right. 
       
      
     an!modN={(amodN)2modNn=2(a(n−1)!modN)nmodNn≥3
 解题脚本:
mport gmpy2
from Crypto.Util.number import *
def Pollards_p_1(N):
    a = 2
    n = 2
    while True:
        a = pow(a, n, N)
        res = gmpy2.gcd(a-1, N)
        if res != 1 and res != N:
            print 'n =', n
            print 'p =', res
            return res
        n += 1
        
e = 0x10001
n = ...
c = ...
p = Pollards_p_1(n)
q = n // p
assert p*q == n
d = gmpy2.invert(e, (p-1)*(q-1))
m = pow(c, d, n)
print long_to_bytes(m)
 
Sequences
Description
I wrote this linear recurrence function, can you figure out how to make it run fast enough and get the flag?Note that even an efficient solution might take several seconds to run. If your solution is taking several minutes, then you may need to reconsider your approach.
import math
import hashlib
import sys
from tqdm import tqdm
import functools
ITERS = int(2e7)
VERIF_KEY = "96cc5f3b460732b442814fd33cf8537c"
ENCRYPTED_FLAG = bytes.fromhex("42cbbce1487b443de1acf4834baed794f4bbd0dfb5df5e6f2ad8a2c32b")
# This will overflow the stack, it will need to be significantly optimized in order to get the answer :)
@functools.cache
def m_func(i):
    if i == 0: return 1
    if i == 1: return 2
    if i == 2: return 3
    if i == 3: return 4
    return 55692*m_func(i-4) - 9549*m_func(i-3) + 301*m_func(i-2) + 21*m_func(i-1)
# Decrypt the flag
def decrypt_flag(sol):
    sol = sol % (10**10000)
    sol = str(sol)
    sol_md5 = hashlib.md5(sol.encode()).hexdigest()
    if sol_md5 != VERIF_KEY:
        print("Incorrect solution")
        sys.exit(1)
    key = hashlib.sha256(sol.encode()).digest()
    flag = bytearray([char ^ key[i] for i, char in enumerate(ENCRYPTED_FLAG)]).decode()
    print(flag)
if __name__ == "__main__":
    sol = m_func(ITERS)
    decrypt_flag(sol)
 
分析
提示指出m_func函数递归太深会导致栈溢出。使用矩阵快速幂算法。
令需要计算的结果为
    
     
      
       
        
         a
        
        
         i
        
       
      
      
       a_i
      
     
    ai ,有:
 
     
      
       
        
         {
        
        
         
          
           
            
           
          
          
           
            
             
             
              
               a
              
              
               0
              
             
             
              =
             
             
              1
              
             
              ,
              
             
              
               a
              
              
               1
              
             
             
              =
             
             
              2
              
             
              ,
              
             
              
               a
              
              
               2
              
             
             
              =
             
             
              3
              
             
              ,
              
             
              
               a
              
              
               3
              
             
             
              =
             
             
              4
              
            
           
          
         
         
          
           
            
           
          
          
           
            
             
             
              
               a
              
              
               i
              
             
             
              =
             
             
              55692
             
             
              
               a
              
              
               
                i
               
               
                −
               
               
                4
               
              
             
             
              −
             
             
              9549
             
             
              
               a
              
              
               
                i
               
               
                −
               
               
                3
               
              
             
             
              +
             
             
              301
             
             
              
               a
              
              
               
                i
               
               
                −
               
               
                2
               
              
             
             
              +
             
             
              21
             
             
              
               a
              
              
               
                i
               
               
                −
               
               
                1
               
              
             
             
             
              (
             
             
              i
             
             
              ≥
             
             
              3
             
             
              )
             
            
           
          
         
        
       
       
         \left\{ \begin{aligned} &a_0=1\,,\,a_1=2\,,\,a_2=3\,,\,a_3=4\,\\ &a_{i}=55692a_{i-4} - 9549a_{i-3} + 301a_{i-2} + 21a_{i-1}\quad(i\geq3)\\ \end{aligned} \right. 
       
      
     {a0=1,a1=2,a2=3,a3=4ai=55692ai−4−9549ai−3+301ai−2+21ai−1(i≥3)
整理得到:
 
     
      
       
        
         
          (
         
         
          
           
            
             
              
               a
              
              
               n
              
             
            
           
          
          
           
            
             
              
               a
              
              
               
                n
               
               
                −
               
               
                1
               
              
             
            
           
          
          
           
            
             
              
               a
              
              
               
                n
               
               
                −
               
               
                2
               
              
             
            
           
          
          
           
            
             
              
               a
              
              
               
                n
               
               
                −
               
               
                3
               
              
             
            
           
          
         
         
          )
         
        
        
         =
        
        
         
          (
         
         
          
           
            
             
              21
             
            
           
           
            
             
              301
             
            
           
           
            
             
              
               −
              
              
               9549
              
             
            
           
           
            
             
              556992
             
            
           
          
          
           
            
             
              1
             
            
           
           
            
             
              0
             
            
           
           
            
             
              0
             
            
           
           
            
             
              0
             
            
           
          
          
           
            
             
              0
             
            
           
           
            
             
              1
             
            
           
           
            
             
              0
             
            
           
           
            
             
              0
             
            
           
          
          
           
            
             
              0
             
            
           
           
            
             
              0
             
            
           
           
            
             
              1
             
            
           
           
            
             
              0
             
            
           
          
         
         
          )
         
        
        
         
          (
         
         
          
           
            
             
              
               a
              
              
               
                n
               
               
                −
               
               
                1
               
              
             
            
           
          
          
           
            
             
              
               a
              
              
               
                n
               
               
                −
               
               
                2
               
              
             
            
           
          
          
           
            
             
              
               a
              
              
               
                n
               
               
                −
               
               
                3
               
              
             
            
           
          
          
           
            
             
              
               a
              
              
               
                n
               
               
                −
               
               
                4
               
              
             
            
           
          
         
         
          )
         
        
        
         =
        
        
         A
        
        
         
          (
         
         
          
           
            
             
              
               a
              
              
               
                n
               
               
                −
               
               
                1
               
              
             
            
           
          
          
           
            
             
              
               a
              
              
               
                n
               
               
                −
               
               
                2
               
              
             
            
           
          
          
           
            
             
              
               a
              
              
               
                n
               
               
                −
               
               
                3
               
              
             
            
           
          
          
           
            
             
              
               a
              
              
               
                n
               
               
                −
               
               
                4
               
              
             
            
           
          
         
         
          )
         
        
       
       
         \left(\begin{matrix}a_n\\a_{n-1}\\a_{n-2}\\a_{n-3}\end{matrix}\right)=\left(\begin{matrix}21&301&-9549&556992\\1&0&0&0\\0&1&0&0\\0&0&1&0\end{matrix}\right) \left(\begin{matrix}a_{n-1}\\a_{n-2}\\a_{n-3}\\a_{n-4}\end{matrix}\right)=A\left(\begin{matrix}a_{n-1}\\a_{n-2}\\a_{n-3}\\a_{n-4}\end{matrix}\right) 
       
      
     ⎝⎜⎜⎛anan−1an−2an−3⎠⎟⎟⎞=⎝⎜⎜⎛21100301010−9549001556992000⎠⎟⎟⎞⎝⎜⎜⎛an−1an−2an−3an−4⎠⎟⎟⎞=A⎝⎜⎜⎛an−1an−2an−3an−4⎠⎟⎟⎞
 递推得:
 
     
      
       
        
         
          (
         
         
          
           
            
             
              
               a
              
              
               n
              
             
            
           
          
          
           
            
             
              
               a
              
              
               
                n
               
               
                −
               
               
                1
               
              
             
            
           
          
          
           
            
             
              
               a
              
              
               
                n
               
               
                −
               
               
                2
               
              
             
            
           
          
          
           
            
             
              
               a
              
              
               
                n
               
               
                −
               
               
                3
               
              
             
            
           
          
         
         
          )
         
        
        
         =
        
        
         A
        
        
         
          (
         
         
          
           
            
             
              
               a
              
              
               
                n
               
               
                −
               
               
                1
               
              
             
            
           
          
          
           
            
             
              
               a
              
              
               
                n
               
               
                −
               
               
                2
               
              
             
            
           
          
          
           
            
             
              
               a
              
              
               
                n
               
               
                −
               
               
                3
               
              
             
            
           
          
          
           
            
             
              
               a
              
              
               
                n
               
               
                −
               
               
                4
               
              
             
            
           
          
         
         
          )
         
        
        
         =
        
        
         
          A
         
         
          2
         
        
        
         
          (
         
         
          
           
            
             
              
               a
              
              
               
                n
               
               
                −
               
               
                2
               
              
             
            
           
          
          
           
            
             
              
               a
              
              
               
                n
               
               
                −
               
               
                3
               
              
             
            
           
          
          
           
            
             
              
               a
              
              
               
                n
               
               
                −
               
               
                4
               
              
             
            
           
          
          
           
            
             
              
               a
              
              
               
                n
               
               
                −
               
               
                5
               
              
             
            
           
          
         
         
          )
         
        
        
         =
        
        
         .
        
        
         .
        
        
         .
        
        
         =
        
        
         
          A
         
         
          
           n
          
          
           −
          
          
           3
          
         
        
        
         
          (
         
         
          
           
            
             
              
               a
              
              
               3
              
             
            
           
          
          
           
            
             
              
               a
              
              
               2
              
             
            
           
          
          
           
            
             
              
               a
              
              
               1
              
             
            
           
          
          
           
            
             
              
               a
              
              
               0
              
             
            
           
          
         
         
          )
         
        
       
       
         \left(\begin{matrix}a_n\\a_{n-1}\\a_{n-2}\\a_{n-3}\end{matrix}\right)=A\left(\begin{matrix}a_{n-1}\\a_{n-2}\\a_{n-3}\\a_{n-4}\end{matrix}\right)=A^2\left(\begin{matrix}a_{n-2}\\a_{n-3}\\a_{n-4}\\a_{n-5}\end{matrix}\right)=...=A^{n-3}\left(\begin{matrix}a_3\\a_2\\a_1\\a_0\end{matrix}\right) 
       
      
     ⎝⎜⎜⎛anan−1an−2an−3⎠⎟⎟⎞=A⎝⎜⎜⎛an−1an−2an−3an−4⎠⎟⎟⎞=A2⎝⎜⎜⎛an−2an−3an−4an−5⎠⎟⎟⎞=...=An−3⎝⎜⎜⎛a3a2a1a0⎠⎟⎟⎞
利用快速幂算法计算 A k A^k Ak,优化后的m_func函数如下:
matrix = [[21,301,-9549,55692],
          [ 1, 0 ,  0  ,  0  ],
          [ 0, 1 ,  0  ,  0  ],
          [ 0, 0 ,  1  ,  0  ]]
def m_func(i):
    s = quickMatrix(matrix,i - 3)
    return 4*s[0][0] + 3*s[0][1] + 2*s[0][2] + 1*s[0][3]
def mulMatrix(x,y):     #矩阵相乘
    ans = [[0 for i in range(4)]for j in range(4)]
    for i in range(4):
        for j in range(4):
            for k in range(4):
                ans[i][j] +=  x[i][k] * y[k][j] % (10**10000)
    return ans
def quickMatrix(m,n):
    E = [[0 for i in range(4)]for j in range(4)]   #单位矩阵E
    for i in range(4):
        E[i][i] = 1
    while(n):
        print(n)
        if n % 2 != 0:
            E = mulMatrix(E,m)
        m = mulMatrix(m,m)
        n >>= 1
    return E
 
运行得到:
picoCTF{b1g_numb3rs_a1c77d6c}










