d低位攻击 & d高位攻击

文章介绍了两种针对RSA加密的攻击策略,包括利用d的低位进行的低位攻击和利用d的高位进行的高位攻击。在低位攻击中,通过计算d的最后512位字节并找到对应的p低字节来获取完整素数p。高位攻击中,利用d的高位信息,通过精度控制在实数环中寻找p的高位部分。这两种方法最终用于解密RSA加密的密文。
摘要由CSDN通过智能技术生成

低位攻击【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位字节)

在这里插入图片描述
exp1:

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_p_low(d_low, e, n)

之后就是正常的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}

于2024/05/10更新

高位攻击【d >> 222 << 222】

题目描述:

from secret import m1
def task1():
    e = 149
    p = getPrime(512)
    q = getPrime(512)
    n = p * q
    d = inverse(e,(p-1)*(q-1))
    return (pow(m1, e, n), d >> 222 << 222, n)
    
c1, leak1, n1 = task1()
print(c1, leak1, n1)
# (89623543982221289730635223555830551523170205418976759060541832483843039074358160566735322009158596405712449020903311144480669706226166537602750967447480664875090686428406188847601970724994074417752345460791736191511081890913041143570455636020205647345764692062144226011846336769477026234106683791286490222089, 138474880017294332349992670187778287774153347391371789199005713563195654993662610111557185709277805165708109047494971468100563949333712521647405765501704478862377527360106399421209690341743821320754482338590671565510629203215009008479290995785318405211007685664887994061938667418220613430135743123498167435264, 146331610798417415036517077006943013321623040860385791423062775325646472298267580898028515394910588437521335092742913111680737790430660749825981979147191282007208147041227246620008377726207734522466015971515317594545750944838673018946440525615131606652748549901880641896940968837669894325535750125282351577689)

假设 l e a k d = d > > 222 < < 222 leak_d = d >> 222 << 222 leakd=d>>222<<222
方法和低位攻击差不多,不过不需要模 2 L 2 2^{\frac{L}{2}} 22L,用RealField(1000)建立一个精度为1000位的实数环,解出来的值p满足:
e ∗ l e a k d ∗ p ≈ k p n + k p + p − k p 2 − k n e*leak_d * p\approx kpn + kp + p - kp^2 - kn eleakdpkpn+kp+pkp2kn
解出来的p与实际p的误差,和 l e a k d leak_d leakd与实际d之间的误差相当,故解出来的p的高位是准确的,后面可能会因进位产生误差,不过影响不大,之后p高位攻击求解的时候把最大限制位数上调几位就行

exp:

from tqdm import *
from Crypto.Util.number import *
def get_full_p(p_high, n,d_high,bits):
    PR.<x> = PolynomialRing(Zmod(n))    
    f = x + p_high
    f = f.monic()
    roots = f.small_roots(X=2^(bits + 4), beta=0.4)  
    if roots:
        x0 = roots[0]
        p = gcd(x0 + p_high, n)
        return ZZ(p)


def find_p_high(d_high, e, n,bits):
    PR.<X> = PolynomialRing(RealField(1000))
    for k in tqdm(range(1, e+1)):
        f=e * d_high * X - (k*n*X + k*X + X-k*X**2 - k*n)
        results = f.roots()
        if results:
            for x in results:
                p_high = int(x[0])
                p = get_full_p(p_high, n,d_high,bits)
                if p and p != 1:
                    return p


c1 = 89623543982221289730635223555830551523170205418976759060541832483843039074358160566735322009158596405712449020903311144480669706226166537602750967447480664875090686428406188847601970724994074417752345460791736191511081890913041143570455636020205647345764692062144226011846336769477026234106683791286490222089
leak1 = 138474880017294332349992670187778287774153347391371789199005713563195654993662610111557185709277805165708109047494971468100563949333712521647405765501704478862377527360106399421209690341743821320754482338590671565510629203215009008479290995785318405211007685664887994061938667418220613430135743123498167435264
n1 = 146331610798417415036517077006943013321623040860385791423062775325646472298267580898028515394910588437521335092742913111680737790430660749825981979147191282007208147041227246620008377726207734522466015971515317594545750944838673018946440525615131606652748549901880641896940968837669894325535750125282351577689
e1 = 149
p1 = find_p_high(leak1, e1, n1,222)
q1 = n1 // p1
d1 = inverse(e1,(p1 - 1) * (p1 - 1))
m1 = pow(c1,int(d1),n1)
# m1 = 93042260506308905687316210296370903867944448843426931916177804361314554938769155297064710450598988156852495157007543827533397400499205420109469753501281147177076078618487311899665501210039745369195187361529223336792457967014013480910834750387942851959412408192660971257781477567993988241665134269163250719147
### 回答1: 在 Modbus 协议中,寄存器地址通常是 16 位的无符号整数,高 8 位表示地址的高位,低 8 位表示地址的低位。由于 Modbus 协议采用大端字节序(Big Endian),因此在数据帧中先发送高位,后发送低位。例如,地址为 0x1234,则先发送 0x12,后发送 0x34。这样可以保证不同机器之间的通信时,字节的顺序是一致的。需要注意的是,不同的设备可能会采用不同的字节序,因此在实际应用中需要进行适当的字节序转换。 ### 回答2: 在Modbus通信协议中,设备地址通常由两个字节组成,一个高位和一个低位。设备地址是用于标识在Modbus网络中的具体设备。这种设备地址编码方式通常被称为地址高位低位。 在Modbus协议中,高位指的是设备地址的高8位,低位指的是设备地址的低8位。设备地址的高位低位组合在一起形成一个完整的设备地址。通过设备地址,Modbus主站可以向特定的从站发送读取或写入数据的指令。 采用地址高位低位的方式可以实现的设备地址范围是0至65535,其中0是广播地址,用于向Modbus网络中的所有从站广播指令。 为了准确地发送指令给特定的从站,Modbus主站需要知道要与之通信的从站的设备地址。通过指定从站的设备地址,主站发送的指令将只会被该从站接收和处理。 设备地址的选择对于Modbus通信的正常运行非常重要。在不同的Modbus网络中,应该为每个从站分配一个唯一的设备地址,以确保通信的准确性和可靠性。 总结起来,Modbus协议中的地址高位低位是用来表示设备地址的编码方式,其中高位指设备地址的高8位,低位指设备地址的低8位。设备地址的选择对于实现可靠的Modbus通信非常重要,因此在配置Modbus网络时应注意给每个从站分配一个唯一的设备地址。 ### 回答3: Modbus是用于在设备之间进行通信的通信协议。在Modbus协议中,指令和数据的地址通常是由两个字节组成的,其中一个字节用于表示地址的高位,另一个字节用于表示地址的低位。 地址高位指的是地址的高字节,它表示整个地址的较高部分。在一个16位的地址中,高位通常位于地址的前8位。 地址低位指的是地址的低字节,它表示整个地址的较低部分。在一个16位的地址中,低位通常位于地址的后8位。 例如,如果我们有一个地址为0x1234的Modbus指令,其中0x12表示地址的高位,0x34表示地址的低位。 在Modbus通信中,地址高位低位的设置非常重要,因为它们决定了指令和数据将在哪个设备的哪个寄存器或输入/输出点上执行。通过正确设置地址高位低位,我们可以确保指令和数据被准确地传输和处理。 总之,Modbus协议中的指令地址由两个字节组成,其中一个字节表示地址的高位,另一个字节表示地址的低位。通过正确设置地址高位低位,可以确保指令和数据被正确地传输和处理。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值