d低位攻击例题

文章目录

  • 题目描述 d & (1 << 512 - 1):
  • 题目分析:
      • 方法一:
      • 方法二:

题目描述 d & (1 << 512 - 1):

n=92896523979616431783569762645945918751162321185159790302085768095763248357146198882641160678623069857011832929179987623492267852304178894461486295864091871341339490870689110279720283415976342208476126414933914026436666789270209690168581379143120688241413470569887426810705898518783625903350928784794371176183
e=3
m=random.getrandbits(512)
c=pow(m,e,n)=56164378185049402404287763972280630295410174183649054805947329504892979921131852321281317326306506444145699012788547718091371389698969718830761120076359634262880912417797038049510647237337251037070369278596191506725812511682495575589039521646062521091457438869068866365907962691742604895495670783101319608530
d&((1<<512)-1)=787673996295376297668171075170955852109814939442242049800811601753001897317556022653997651874897208487913321031340711138331360350633965420642045383644955

题目分析:

 必备知识:
 python中 & 为 符号与,即符号左右两边都为真,结果才为真
 eg:
 1 & 1 = 1
 1 & 0 = 0
 0 & 1 = 0
 0 & 0 = 0
 1 << 512 - 1 = 512 个 1 组合在一起
 d & (1 << 512 - 1) = d_low(d的最后512位字节)

d低位攻击例题_第1张图片

方法一:

def get_full_p(p_low, n,d_low):
    PR.<x> = PolynomialRing(Zmod(n))
    d_lowbits = d_low.nbits()
    nbits = n.nbits()
    p_lowbits = p_low.nbits()
    f = 2^p_lowbits*x + p_low
    f = f.monic()
    roots = f.small_roots(X=2^(nbits//2-p_lowbits), beta=0.4)  
    if roots:
        x0 = roots[0]
        p = gcd(2^d_lowbits*x0 + p_low, n)
        return ZZ(p)


def find_p_low(d_low, e, n):
    X = var('X')
    for k in range(1, e+1):
        results = solve_mod([e*d_low*X == k*n*X + k*X + X-k*X**2 - k*n], 2^d_low.nbits())
        for x in results:
            p_low = ZZ(x[0])
            p = get_full_p(p_low, n,d_low)
            if p and p != 1:
                return p


n = 92896523979616431783569762645945918751162321185159790302085768095763248357146198882641160678623069857011832929179987623492267852304178894461486295864091871341339490870689110279720283415976342208476126414933914026436666789270209690168581379143120688241413470569887426810705898518783625903350928784794371176183
c = 56164378185049402404287763972280630295410174183649054805947329504892979921131852321281317326306506444145699012788547718091371389698969718830761120076359634262880912417797038049510647237337251037070369278596191506725812511682495575589039521646062521091457438869068866365907962691742604895495670783101319608530
d_low = 787673996295376297668171075170955852109814939442242049800811601753001897317556022653997651874897208487913321031340711138331360350633965420642045383644955
e = 3
find_p0(d_low, e, n)

方法二:

def get_full_(p_low, n):
    PR.<x> = PolynomialRing(Zmod(n), implementation='NTL')
    p = x * 2 ^ 512 + p_low
    root = (p - n).monic().small_roots(X=2 ^ 128, beta=0.4) # 这一行不太清楚,等我弄清楚了再说
    if root:
        return p(root[0])
    return None

def find_p_low(d_low, n, c):
    maybe_p = []
    for k in range(1, 4):
        p = var('p')
        p0 = solve_mod([3 * p * d_low == p + k * (n * p - p ^ 2 - n + p)], 2 ^ 512)
        maybe_p += [int(x[0]) for x in p0]

    for x in maybe_p:
        P = get_full_p(x, n)
        if P: break

    P = int(P)
    Q = n // P

    assert P * Q == n

    d = inverse_mod(3, (P - 1) * (Q - 1))
    print(d)


n = 92896523979616431783569762645945918751162321185159790302085768095763248357146198882641160678623069857011832929179987623492267852304178894461486295864091871341339490870689110279720283415976342208476126414933914026436666789270209690168581379143120688241413470569887426810705898518783625903350928784794371176183
c = 56164378185049402404287763972280630295410174183649054805947329504892979921131852321281317326306506444145699012788547718091371389698969718830761120076359634262880912417797038049510647237337251037070369278596191506725812511682495575589039521646062521091457438869068866365907962691742604895495670783101319608530
d_low = 787673996295376297668171075170955852109814939442242049800811601753001897317556022653997651874897208487913321031340711138331360350633965420642045383644955

find_p_low(d_low, n, c)
  • 之后就是正常的rsa解密了
import gmpy2
from Crypto.Util.number import *
p = 9188765830170326258642510026168563497927415242471400727621853319326260905122407669621339984215654143516262932956971178004512056542245685884515054294531083
n = 92896523979616431783569762645945918751162321185159790302085768095763248357146198882641160678623069857011832929179987623492267852304178894461486295864091871341339490870689110279720283415976342208476126414933914026436666789270209690168581379143120688241413470569887426810705898518783625903350928784794371176183
c = 56164378185049402404287763972280630295410174183649054805947329504892979921131852321281317326306506444145699012788547718091371389698969718830761120076359634262880912417797038049510647237337251037070369278596191506725812511682495575589039521646062521091457438869068866365907962691742604895495670783101319608530
q = n // p
phi = (p-1)*(q-1)
e = 3
d = gmpy2.invert(e,phi)
m = pow(c,d,n)
print(long_to_bytes(m))
  • 得到:FLAG{2^8rsa5ab086745f6ec745619a8b65fe4ec560}

你可能感兴趣的:(密码RSA,高位攻击,python,python,密码学,安全)