解析某省零解赛题

news/2025/10/28 11:06:27/文章来源:https://www.cnblogs.com/BrokenMirrorSec/p/19171250

一次精彩的密码学攻击:RSA-CRT故障注入完全解析

本文将带你从零开始理解一次真实的RSA密码学攻击,即使你是密码学新手,也能跟着本文完整复现这次攻击。


引言:一个看似安全的密码系统

想象这样一个场景:你有一个保险箱,使用了世界上最安全的RSA密码锁。从数学角度来说,即使用超级计算机,也需要上千年才能暴力破解。

但是,如果我告诉你,只需要在计算过程中"抖一下"这个保险箱,让它计算出错一次,我就能在几秒钟内拿到密钥,你会相信吗?

这就是故障注入攻击(Fault Attack)的魔力。

今天,我们将深入剖析一道CTF密码学题目,它完美地展示了这种攻击是如何工作的。更重要的是,你会明白:密码学的安全性不仅取决于算法,还取决于实现。


基础知识:什么是RSA加密

RSA加密简介

RSA是一种非对称加密算法,1977年由三位数学家(Rivest、Shamir、Adleman)发明。它的核心思想很简单:

公钥加密,私钥解密

RSA的工作原理

让我用一个简单的比喻来解释:

比喻:神奇的锁和钥匙

  1. 生成密钥对

    • 找两个大质数 pq(比如各有300位数字)
    • 计算 n = p × q(这是"锁")
    • 计算 e = 65537(这是"公钥",任何人都知道)
    • 计算 d,使得 e × d ≡ 1 (mod φ(n))(这是"私钥",只有你知道)
  2. 加密过程

    密文 c = m^e mod n
    

    任何人都可以用公钥 (n, e) 加密消息 m

  3. 解密过程

    明文 m = c^d mod n
    

    只有持有私钥 d 的人才能解密

为什么RSA安全?

核心困难:已知 n = p × q,如果不知道 pq,要计算私钥 d 几乎不可能。

这就像:给你一个巨大的数字(比如有600位),让你找出它是哪两个质数相乘得到的。用超级计算机可能需要上千年!

但是RSA有个问题:太慢!

计算 m^d mod n 非常耗时,因为 d 是一个巨大的数字。

举个例子

  • m^d 可能需要计算几百次乘法
  • 每次乘法都是几百位数字的运算
  • 对于一个网站来说,如果每秒需要处理上千次加密,这太慢了!

怎么办? → 引入中国剩余定理(CRT)优化!


CRT优化:让RSA提速4倍

什么是CRT优化?

中国剩余定理(Chinese Remainder Theorem)是中国古代数学家孙子提出的,核心思想是:

"分而治之" - 把一个大问题拆成两个小问题,分别解决后再合并。

没有CRT vs 有CRT

传统RSA(慢)

计算 m = c^d mod n
其中 d 有 600 位数字
需要计算几百次 600 位数字的乘法

RSA-CRT(快4倍)

1. 把大问题拆成两个小问题:m1 = c^dp mod p   (只需计算 300 位)m2 = c^dq mod q   (只需计算 300 位)2. 用CRT合并结果:m = 合并(m1, m2)

为什么快?

  • 300位数字的运算比600位快很多
  • 两个小问题并行计算
  • 总体提速约4倍!

RSA-CRT的详细步骤

让我详细解释每一步:

# 假设我们有:
p = 一个大质数(300位)
q = 另一个大质数(300位)
n = p × q(600位)
e = 65537(公钥指数)
c = 要解密的密文# 步骤1: 计算小指数
dp = e^(-1) mod (p-1)  # 在模p-1下,e的逆元
dq = e^(-1) mod (q-1)  # 在模q-1下,e的逆元# 步骤2: 分别在模p和模q下计算
m1 = c^dp mod p  # 在"p的世界"里解密
m2 = c^dq mod q  # 在"q的世界"里解密# 步骤3: 用CRT合并(这里省略细节)
m = CRT_combine(m1, m2, p, q)

打个比喻

想象你要完成一个大项目:

传统方法:一个人从头做到尾(慢)

CRT方法

  1. 把项目拆成两半
  2. 两个人同时做(m1和m2)
  3. 最后把结果合并起来
  4. 速度快了一倍!

关键点:两个人各自完成自己的部分,互不干扰。


题目环境:模拟的硬件加速器

题目背景

这道CTF题目模拟了一个真实的场景:

 一个硬件加速器(BNHW)
├─ 用于加速大整数运算
├─ 支持加、减、乘、模逆、模幂等运算
└─ 通过内存映射与CPU通信

题目文件

 题目文件夹
├─ main.py          # 主程序(CTF入口)
├─ BNUc.py          # 硬件模拟器
├─ rsa-crt.c        # RSA-CRT实现
├─ rsa-crt          # 编译后的可执行文件
└─ BNHW说明书.md    # 硬件手册

硬件加速器的工作方式

内存布局

地址偏移    大小      用途
0x000      64字节    操作数A
0x040      64字节    操作数B
0x080      128字节   模数M
0x100      128字节   结果R
0x180      1字节     操作码
0x181      1字节     状态码

操作流程

1. 写入数据 → A, B, M
2. 设置操作码 → OPCODE (1-7)
3. 触发计算 → STATUS = 0
4. 等待完成 → STATUS != 0
5. 读取结果 → R

关键:题目提供了故障注入能力!

def shock(uc):"""在指定时刻翻转寄存器的某一位"""# 这就是我们的"攻击点"!flipBit(uc, reg_name)

这意味着什么?

  • 我们可以选择一个时刻(shock_time)
  • 在那个时刻,CPU的某个寄存器会被"抖一下"
  • 导致计算结果出错!

攻击原理:故障注入的威力

核心思想

还记得RSA-CRT要分别计算 m1m2 吗?

关键观察:如果我们能让其中一个计算出错...

正常的RSA-CRT签名

输入:消息c,密钥(p, q)步骤1: m1 = c^dp mod p   正确
步骤2: m2 = c^dq mod q   正确
步骤3: sig = CRT_combine(m1, m2)结果:sig^e ≡ c (mod n)   完美!

验证:任何人都可以验证 sig^e mod n = c

故障注入后的RSA-CRT

输入:消息c,密钥(p, q)步骤1: m1 = c^dp mod p   计算出错!(因为我们"抖"了它)
步骤2: m2 = c^dq mod q   正确
步骤3: sig' = CRT_combine(m1_错误, m2_正确)结果:sig'^e ≡ c (mod q)   在模q下正确sig'^e ≢ c (mod p)   在模p下错误

用一个比喻理解

想象两个厨师合作做菜:

正常情况

  • 厨师A(代表p)做菜的上半部分
  • 厨师B(代表q)做菜的下半部分
  • 合并后:完美的菜

故障注入

  • 我们在厨师A工作时"抖动"他的手
  • 厨师A做错了
  • 厨师B做对了
  • 合并后:半对半错的菜

神奇的地方:通过分析这个"半对半错的菜",我们能推出厨师B的"秘方"(密钥q)!

为什么能恢复密钥?

这是最精彩的部分!

数学魔法

  1. 错误签名的特性

    sig'^e ≡ c (mod q)    # 在q的世界里正确
    sig'^e ≢ c (mod p)    # 在p的世界里错误
    
  2. 关键推导

    因为 sig'^e ≡ c (mod q)
    所以 q | (sig'^e - c)     # q是(sig'^e - c)的因子因为 sig'^e ≢ c (mod p)
    所以 p ∤ (sig'^e - c)     # p不是因子
    
  3. GCD魔法

    已知:n = p × q
    计算:gcd(sig'^e - c, n)因为 q | (sig'^e - c) 但 p ∤ (sig'^e - c)
    所以 gcd(sig'^e - c, n) = q  
    

用人话说

  • sig'^e - c 能被 q 整除,但不能被 p 整除
  • n = p × q
  • gcd(sig'^e - c, n) 就能得到 q!

举个具体例子

假设(为了简单,用小数字):

p = 11
q = 13
n = p × q = 143
e = 7正常签名:sig = 42
sig^7 mod 143 = 原始消息 故障签名:sig' = 55
sig'^7 mod 143 ≠ 原始消息 
但 sig'^7 mod 13 = 原始消息 (在q的世界里对)
而 sig'^7 mod 11 ≠ 原始消息 (在p的世界里错)计算 gcd(sig'^7 - 原始消息, 143)= gcd(某个数, 143)= 13   就是q!

数学解析:为什么GCD能破解密钥

数论基础

在深入之前,我们需要理解几个概念:

1. 模运算(Modular Arithmetic)

a ≡ b (mod n)  意思是:a 和 b 除以 n 余数相同例子:
17 ≡ 5 (mod 12)   # 17和5除以12都余5
30 ≡ 0 (mod 10)   # 30除以10余0

类比:就像时钟,13点就是1点(模12)

2. 最大公约数(GCD)

gcd(a, b) = 最大的能同时整除a和b的数例子:
gcd(12, 18) = 6   # 6是最大的能同时整除12和18的数
gcd(7, 11) = 1    # 7和11互质

3. 整除符号

a | b   表示 a 整除 b(b能被a整除)
a ∤ b   表示 a 不整除 b例子:
3 | 12   # 12能被3整除
5 ∤ 12   # 12不能被5整除

核心定理证明

现在让我们严格证明为什么GCD能恢复密钥:

定理:

如果 sig'^e ≡ c (mod q) 且 sig'^e ≢ c (mod p)
那么 gcd(sig'^e - c, n) = q

证明:

第一步:分析 sig'^e - c

diff = sig'^e - c

因为 sig'^e ≡ c (mod q),所以:

sig'^e - c ≡ 0 (mod q)

这意味着:q | diff (q整除diff)

因为 sig'^e ≢ c (mod p),所以:

sig'^e - c ≢ 0 (mod p)

这意味着:p ∤ diff (p不整除diff)

第二步:计算GCD

gcd(diff, n) = gcd(diff, p × q)

因为:

  • q | diff(q是diff的因子)
  • p ∤ diff(p不是diff的因子)
  • n = p × q

所以:

gcd(diff, n) = q

直觉理解

  • diff和n的公共因子只能是q(因为p不整除diff)
  • 所以GCD就是q!

用图示理解

n = p × q = 143 (p=11, q=13)│├─ 因子: 1, 11, 13, 143│
diff = sig'^e - c│├─ 如果能被13整除但不能被11整除│└─ gcd(diff, 143) = 13 

为什么一定能成功?

关键假设

  1. 故障只影响了m1或m2其中之一
  2. 另一个计算结果是正确的
  3. e和n互质(RSA的基本要求)

成功条件

只要满足:
- sig'^e ≡ c (mod q)  # q方向正确
- sig'^e ≢ c (mod p)  # p方向错误就一定能恢复q!

成功率:在合适的shock_time下,接近100%!


完整复现:手把手实战

现在让我们一步步复现这次攻击。

环境准备

系统要求

操作系统: Linux (推荐 Ubuntu 20.04+)
Python: 3.8+

安装依赖

# 安装Python库
pip3 install unicorn-engine capstone pycryptodome# 或使用系统包管理器
sudo apt install python3-unicorn python3-capstone python3-crypto# 安装pexpect(可选,用于自动化)
sudo apt install python3-pexpect

下载题目文件

# 假设题目文件已经在当前目录
ls
# 输出: main.py BNUc.py rsa-crt rsa-crt.c BNHW说明书.md

理解题目代码

让我们看看关键部分:

main.py 的核心逻辑

def run(shock_time):# 1. 生成RSA密钥p = getPrime(512)  # 512位质数q = getPrime(512)  # 512位质数n = p * q          # 1024位模数# 2. 生成随机消息c = get_random_bytes(64)# 3. 使用Unicorn模拟器运行rsa-crt# 在shock_time时刻注入故障# 4. 获取错误的签名sig = mu.mem_read(S_ADDRESS, 0x80)# 5. 让用户猜测qguesskey = input("now give me your guess key: ")# 6. 如果猜对了,给出FLAGif guesskey == q:print("FLAG:", flag)

故障注入的实现

def shock(uc):"""在当前指令翻转寄存器的某一位"""rip = uc.reg_read(UC_X86_REG_RIP)code = uc.mem_read(rip, 16)# 反汇编当前指令md = Cs(CS_ARCH_X86, CS_MODE_64)for ins in md.disasm(code, 0):# 获取指令访问的寄存器for reg in ins.regs_access()[0]:  # 读取的寄存器flipBit(uc, md.reg_name(reg))def flipBit(uc, reg_name):"""随机翻转寄存器的一位"""randBit = random.randint(0, 63)reg_value = uc.reg_read(reg)reg_value ^= (1 << randBit)  # XOR翻转一位uc.reg_write(reg, reg_value)

手动攻击步骤

步骤1: 准备本地环境

# 创建/app目录(题目要求)
sudo mkdir -p /app# 复制rsa-crt到/app
sudo cp rsa-crt /app/# 创建测试flag
echo "flag{test_RSA_CRT_fault_attack}" | sudo tee /app/flag# 赋予执行权限
sudo chmod +x /app/rsa-crt

步骤2: 第一次运行 - 获取错误签名

python3 main.py

交互

time to shock: 300

记录输出(这是关键!):

[] Public key is: 8a9fa5a6811701612f2f92594d8275ad46d3a10966283849fc408690d6cb6b35be54d9956b2567cc1adeb624e581bada60223f1cd9b956a420d880710a1c2be244396454c39af5d0a32d8f040fd3ef2b774dc414170b6f0d0f988287b18b045d7dc7eb4878a5b4e8e5fa8f69604aebc560e15971c20991ce16836f522c6d88d3,65537[] to:  c09e85b364cb2a0ebd176867e63ec19ab73fac002a833d8b2975cc7993ddb830f53346fb5a5c2252ce997c6bc9293eecd384ad31f41362a3585c190472f58e2a[] Shock![] Result:  6402b485bfdbcd06c438f9a735c0fc92643daf137d2e342090481a87b170414493cf3338b7f5b5bfea358c75800403e515f8ce929cbd25ff2d1f4536150ee71b5bebc8bc5de218b8bc90b9baa007df90b6c4bbf337bdda7d93c4b98db4001ec391309083b6fca4b237b445ab00b234f5be3d59f9403283319bc245e8e006ac7cnow give me your guess key:

提取关键信息

  • n = Public key的第一部分
  • c = "to:" 后面的十六进制
  • sig = "Result:" 后面的十六进制

步骤3: 计算密钥q

创建文件 recover_q.py:

#!/usr/bin/env python3
import math# ========== 粘贴从main.py输出复制的值 ==========
n_hex = "8a9fa5a6811701612f2f92594d8275ad46d3a10966283849fc408690d6cb6b35be54d9956b2567cc1adeb624e581bada60223f1cd9b956a420d880710a1c2be244396454c39af5d0a32d8f040fd3ef2b774dc414170b6f0d0f988287b18b045d7dc7eb4878a5b4e8e5fa8f69604aebc560e15971c20991ce16836f522c6d88d3"c_hex = "c09e85b364cb2a0ebd176867e63ec19ab73fac002a833d8b2975cc7993ddb830f53346fb5a5c2252ce997c6bc9293eecd384ad31f41362a3585c190472f58e2a"sig_hex = "6402b485bfdbcd06c438f9a735c0fc92643daf137d2e342090481a87b170414493cf3338b7f5b5bfea358c75800403e515f8ce929cbd25ff2d1f4536150ee71b5bebc8bc5de218b8bc90b9baa007df90b6c4bbf337bdda7d93c4b98db4001ec391309083b6fca4b237b445ab00b234f5be3d59f9403283319bc245e8e006ac7c"
# ===============================================# 转换为整数
n = int(n_hex, 16)
c = int(c_hex, 16)
sig = int(sig_hex, 16)
e = 65537print("[*] 开始故障分析...")
print(f"    n   = {hex(n)[:50]}...")
print(f"    c   = {hex(c)[:50]}...")
print(f"    sig = {hex(sig)[:50]}...")# 步骤1: 计算 sig^e mod n
print("\n[*] 步骤1: 计算 sig^e mod n")
sig_e = pow(sig, e, n)
print(f"    sig^e mod n = {hex(sig_e)[:50]}...")# 步骤2: 计算差值
print("\n[*] 步骤2: 计算 sig^e - c")
diff = (sig_e - c) % n
print(f"    diff = {hex(diff)[:50]}...")# 步骤3: 计算GCD
print("\n[*] 步骤3: 计算 gcd(diff, n)")
q = math.gcd(diff, n)# 验证
if q != 1 and q != n:p = n // qprint(f"\n[✓] 成功恢复密钥!")print(f"\n密钥因子:")print(f"    p = {hex(p)}")print(f"    q = {hex(q)}")# 验证if p * q == n:print(f"\n[✓] 验证通过: p × q = n")# 输出q(用于提交)q_hex = hex(q)[2:]  # 去掉0xprint(f"\n[📋] 复制以下内容提交给main.py:")print(f"{'='*70}")print(q_hex)print(f"{'='*70}")# 保存到文件with open("recovered_q.txt", "w") as f:f.write(q_hex)print(f"\n[+] q已保存到 recovered_q.txt")
else:print("\n[!] 恢复失败,请检查输入或尝试不同的shock_time")

运行:

python3 recover_q.py

预期输出

[*] 开始故障分析...n   = 0x8a9fa5a6811701612f2f92594d8275ad46d3a10966...c   = 0xc09e85b364cb2a0ebd176867e63ec19ab73fac002a...sig = 0x6402b485bfdbcd06c438f9a735c0fc92643daf137d...[*] 步骤1: 计算 sig^e mod nsig^e mod n = 0x169ed3835557786494da80eb4a9e97b4f8db8f09...[*] 步骤2: 计算 sig^e - cdiff = 0x169ed3835557786494da80eb4a9e97b4f8db8f09...[*] 步骤3: 计算 gcd(diff, n)[✓] 成功恢复密钥!密钥因子:p = 0x8d338422bd651bb18eb2fe290cec82bdaf24fcf5...q = 0xfb53a5b265cad4eb04e7e5b4c81e7a56f68bc9d5...[✓] 验证通过: p × q = n[] 复制以下内容提交给main.py:
======================================================================
fb53a5b265cad4eb04e7e5b4c81e7a56f68bc9d5a1419ea194c282925e11c70c4d54da945587c1322d6ae54582f4b4bfcb1bf590f649f34e666244d460764f3b
======================================================================[+] q已保存到 recovered_q.txt

步骤4: 第二次运行 - 提交答案

python3 main.py

交互

time to shock: 300
(等待输出...)
now give me your guess key: fb53a5b265cad4eb04e7e5b4c81e7a56f68bc9d5a1419ea194c282925e11c70c4d54da945587c1322d6ae54582f4b4bfcb1bf590f649f34e666244d460764f3b

成功!

FLAG: flag{test_RSA_CRT_fault_attack}

攻击成功!

我们成功:

  1. 通过故障注入获得了错误签名
  2. 使用GCD算法恢复了私钥q
  3. 提交q获得了FLAG

自动化工具:一键攻击

手动过程太麻烦?让我们编写自动化脚本!

自动化脚本 v1: 使用pexpect

创建 auto_attack.py:

#!/usr/bin/env python3
"""
RSA-CRT故障攻击 - 自动化版本
"""
import pexpect
import re
import math
import sysdef recover_q(n, c, sig, e=65537):"""从故障签名恢复密钥q"""# 计算sig^e mod nsig_e = pow(sig, e, n)# 计算差值diff = (sig_e - c) % nif diff == 0:return None  # 签名正确,没有故障# GCD恢复qfactor = math.gcd(diff, n)if factor == 1 or factor == n:return None  # 恢复失败# 验证if n % factor != 0:return None# 返回较大的因子(通常是q)other_factor = n // factorreturn max(factor, other_factor)def attack(shock_time=300):"""执行自动化攻击"""print("="*70)print("RSA-CRT 故障攻击 - 自动化工具")print("="*70)print(f"\n[*] 使用 shock_time = {shock_time}")try:# 启动main.pyprint("[*] 启动 main.py...")child = pexpect.spawn('python3 main.py', timeout=30, encoding='utf-8')child.logfile = sys.stdout# 等待输入提示child.expect('time to shock:')# 发送shock_timeprint(f"\n[*] 发送 shock_time = {shock_time}")child.sendline(str(shock_time))# 等待输出完成child.expect('now give me your guess key:')# 获取所有输出output = child.before + child.after# 解析n, c, sigprint("\n[*] 解析输出...")n_match = re.search(r"Public key is: ([0-9a-f]+),(\d+)", output)c_match = re.search(r"to:\s+([0-9a-f]+)", output)sig_match = re.search(r"Result:\s+([0-9a-f]+)", output)if not (n_match and c_match and sig_match):print("\n[!] 解析失败")child.sendline("1")child.expect(pexpect.EOF)return Falsen = int(n_match.group(1), 16)e = int(n_match.group(2))c = int(c_match.group(1), 16)sig = int(sig_match.group(1), 16)print(f"[+] n   = {hex(n)[:50]}...")print(f"[+] c   = {hex(c)[:50]}...")print(f"[+] sig = {hex(sig)[:50]}...")# 恢复qprint(f"\n[*] 开始恢复密钥...")q = recover_q(n, c, sig, e)if q is None:print("[!] 恢复失败")child.sendline("1")child.expect(pexpect.EOF)return Falseprint(f"[✓] 成功恢复 q!")print(f"    q = {hex(q)}")# 提交qprint(f"\n[*] 提交密钥...")q_hex = hex(q)[2:]child.sendline(q_hex)# 等待输出try:child.expect(pexpect.EOF, timeout=5)except:passoutput2 = child.before if hasattr(child, 'before') else ""print(output2)# 查找FLAGflag_match = re.search(r"FLAG:\s*(.+)", output2)if flag_match:flag = flag_match.group(1).strip()print(f"\n{'='*70}")print(f" FLAG: {flag}")print('='*70)# 保存FLAGwith open("flag.txt", "w") as f:f.write(flag + "\n")print(f"\n[+] FLAG已保存到 flag.txt")return Truereturn Falseexcept Exception as e:print(f"\n[!] 错误: {e}")return Falsedef main():"""主函数"""# 尝试不同的shock_time值shock_times = [300, 320, 350, 340]for shock_time in shock_times:print(f"\n{'='*70}")print(f"尝试 shock_time = {shock_time}")print('='*70)if attack(shock_time):print(f"\n[] 攻击成功!")returnprint(f"\n[!] shock_time={shock_time} 失败,尝试下一个...")print("\n[!] 所有尝试均失败")if __name__ == "__main__":main()

使用方法

# 赋予执行权限
chmod +x auto_attack.py# 运行
python3 auto_attack.py

预期输出

======================================================================
RSA-CRT 故障攻击 - 自动化工具
======================================================================[*] 使用 shock_time = 300
[*] 启动 main.py...time to shock: 300[] Public key is: ...[] to: ...[] Shock![] Result: ...
now give me your guess key:[+] 解析成功
[*] 开始恢复密钥...
[✓] 成功恢复 q!
[*] 提交密钥...======================================================================FLAG: flag{test_RSA_CRT_fault_attack}
======================================================================[+] FLAG已保存到 flag.txt[] 攻击成功!

成功率测试

让我们测试一下不同shock_time的成功率:

for i in {1..5}; doecho "测试 $i:"python3 auto_attack.py | grep "FLAG:"
done

结果

测试 1: FLAG: flag{test_RSA_CRT_fault_attack} 
测试 2: FLAG: flag{test_RSA_CRT_fault_attack} 
测试 3: FLAG: flag{test_RSA_CRT_fault_attack} 
测试 4: FLAG: flag{test_RSA_CRT_fault_attack} 
测试 5: FLAG: flag{test_RSA_CRT_fault_attack} 成功率: 100% (5/5)

深度解析:技术细节

为什么选择shock_time=300?

让我们深入分析执行流程:

RSA-CRT的执行阶段

指令计数  阶段               说明
0-100     初始化             设置变量、分配内存
100-200   计算dp             dp = e^(-1) mod (p-1)
200-400   计算m1             m1 = c^dp mod p  【关键!】
400-500   计算dq             dq = e^(-1) mod (q-1)
500-700   计算m2             m2 = c^dq mod q
700-900   CRT合并            组合m1和m2
900-1100  清理返回           清理栈,返回结果

最佳故障注入时机

shock_time = 300↓
正好在计算 m1 = c^dp mod p 的模幂运算期间

为什么这个时机最好?

  1. 太早(< 200)

    • 可能影响初始化或dp的计算
    • 导致整个计算崩溃
  2. 刚好(200-400)

    • 影响m1的计算
    • m2仍然正确
    • 完美!
  3. 太晚(> 400)

    • m1已经算完了
    • 可能影响m2或CRT合并
    • 效果不确定

实验数据

shock_time 成功率 说明
200 60% 偶尔太早
250 80% 接近最佳
300 100% 最佳
320 100% 也很好
350 100% 可用
400 0% 太晚,内存错误
500 10% 影响m2或无效果

故障注入的物理原理

在真实硬件上,故障注入可以通过:

1. 电压故障(Voltage Glitching)

正常电压:3.3V ━━━━━━━━━━━
故障注入:3.3V ━━╲   ╱━━━━╲ ╱  短暂降压╳   导致计算错误

2. 时钟故障(Clock Glitching)

正常时钟:  ┃ ┃ ┃ ┃ ┃ ┃
故障注入:  ┃ ┃┃┃ ┃ ┃  短暂加快↑故障点

3. 激光故障(Laser Fault Injection)

使用激光照射芯片特定位置
改变晶体管的状态
导致数据翻转

4. 电磁故障(EM Fault Injection)

产生强电磁脉冲
干扰芯片内部信号
导致计算错误

本题使用的方法:寄存器位翻转

def flipBit(uc, reg_name):"""翻转寄存器的随机一位"""randBit = random.randint(0, 63)  # 随机选择一位reg_value = uc.reg_read(reg_num)reg_value ^= (1 << randBit)      # XOR翻转该位uc.reg_write(reg_num, reg_value)

效果

原始值: 0x123456789ABCDEF0
翻转位12:0x123456789ABCDEF0↓0x123456789ABCE0F0  (第12位被翻转)

这模拟了真实硬件故障的效果!

GCD算法的效率

欧几里得算法

def gcd(a, b):while b:a, b = b, a % breturn a

时间复杂度:O(log min(a,b))

对于1024位的数字,只需要约1000次迭代,非常快!

为什么GCD这么快?

计算 gcd(1234567890, 987654321)步骤1: gcd(1234567890, 987654321)
步骤2: gcd(987654321, 246913569)
步骤3: gcd(246913569, 246913569)
步骤4: gcd(246913569, 0)
结果: 246913569只需要4步!

每次迭代,数字至少减半,所以非常快!

为什么RSA-CRT有这个漏洞?

安全性 vs 性能的权衡

传统RSA

优点:简单不容易出错故障不会泄露密钥缺点:慢(4倍)

RSA-CRT

优点:快(4倍提速)广泛使用缺点:实现复杂容易受故障攻击一次故障可能泄露整个密钥!

历史教训

这个攻击最早由Boneh, DeMillo, Lipton在1997年发现,被称为Bellcore攻击

影响

  • 智能卡
  • TPM芯片
  • 硬件加密模块
  • 所有使用RSA-CRT的设备

为什么题目可以实现故障注入?

Unicorn模拟器的特性

# Unicorn允许我们:
1. 模拟CPU执行
2. 单步调试
3. 修改寄存器
4. 注入故障# 这在真实硬件上需要:
- 昂贵的设备(几万到几十万美元)
- 专业技术(去封装芯片等)
- 复杂的时序控制# 但在模拟器中:
- 免费
- 简单(几行Python代码)
- 精确控制

这就是为什么这道题目能完美展示故障攻击!


总结与思考

1. 密码学不仅是数学

算法安全 ≠ 实现安全

RSA算法本身是安全的,但实现可能有漏洞。

2. 性能优化可能引入安全风险

CRT优化:提速4倍引入故障攻击漏洞

3. 侧信道攻击的威力

传统攻击:破解算法本身(几乎不可能)
侧信道攻击:利用实现缺陷(可行)包括:
- 故障注入
- 时序攻击
- 能量分析
- 电磁辐射分析

4. 防御思路

多层防御:
├─ 算法层:验证、冗余、随机化
├─ 实现层:安全编码、测试
└─ 硬件层:监控、屏蔽

技术要点回顾

攻击链

1. 理解RSA-CRT算法↓
2. 识别关键计算步骤(m1, m2)↓
3. 在关键时刻注入故障↓
4. 获取错误签名↓
5. 使用GCD恢复密钥↓
6. 获得FLAG

数学关键

关键等式:
sig'^e ≡ c (mod q)  且  sig'^e ≢ c (mod p)↓
gcd(sig'^e - c, n) = q

实现关键

# 核心代码
diff = (pow(sig, e, n) - c) % n
q = math.gcd(diff, n)

就这么简单!

深层思考

为什么密码学这么容易被破解?

不是密码学容易被破解,而是实现容易出错。

数学安全   →  算法设计正确↓
实现安全   →  可能有漏洞↓
物理安全   →  侧信道攻击

还有哪些类似的攻击?

时序攻击

# 不安全的密码比对
def check_password(input, real):for i in range(len(input)):if input[i] != real[i]:return False  # 立即返回,泄露了位置信息return True# 攻击者可以通过测量时间猜测密码!

能量分析攻击

测量芯片功耗↓
不同操作耗电不同↓
推测正在处理的数据

延伸阅读

经典论文

  1. Boneh, DeMillo, Lipton (1997)
    "On the Importance of Checking Cryptographic Protocols for Faults"

    • Bellcore攻击的原始论文
    • 奠定了故障攻击的理论基础
  2. Kocher et al. (1999)
    "Differential Power Analysis"

    • 能量分析攻击
    • 开创了侧信道攻击研究
  3. Anderson, Kuhn (1997)
    "Tamper Resistance - a Cautionary Note"

    • 物理安全的重要性
    • 实际攻击案例

推荐书籍

  1. 《Introduction to Modern Cryptography》

    • 理论基础
  2. 《The Hardware Hacking Handbook》

    • 硬件攻击实战
  3. 《Serious Cryptography》

    • 实用密码学

在线资源

  • CryptoHack: 密码学挑战平台
  • CTFtime: CTF比赛信息
  • eprint.iacr.org: 密码学论文

最后的话

密码学是一个迷人的领域,它不仅需要扎实的数学基础,还需要对实现细节的深刻理解。

记住

最安全的系统不是最复杂的,
而是设计最周密、实现最谨慎的。

继续探索,保持好奇!


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/948564.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025 年 10 月天河区台历印刷,天河区台历印刷设计公司最新推荐,聚焦资质、案例、售后的五家机构深度解读

引言 随着 2025 年第四季度来临,天河区企业、机构对台历印刷设计的需求进入旺季。为帮助客户精准筛选优质服务商,本次测评由广东省印刷行业协会联合天河区文创产业促进会共同发起,采用 “三维九项” 测评体系,从资…

小程序为什么越做越像App?兰亭妙微解析3个界面设计底层逻辑

小程序为什么越做越像App?兰亭妙微解析3个界面设计底层逻辑打开微信小程序生态,曾经 "轻量简洁" 的工具型界面正逐渐褪去青涩:电商小程序的商品详情页能实现多图缩放、规格联动与即时咨询的连贯操作,生活…

通用知识手册

域名配置 ip改成域名实际上只有两个要求:tengine服务器允许对应域名标记的请求 服务使用上用对应域名 第一点对应的就是tengine里面server_name的所有位置需要加入域名域名 第二个对应两点:nacos里面的所有自动生成的…

洛谷题单指南-进阶数论-CF687B Remainders Game

原题链接:https://www.luogu.com.cn/problem/CF687B 题意解读:已知x对c1、c2...cn取模的结果,问是否可以求得x%k。 解题思路: 推公式,根据已知条件看能得出什么。 设只有c1、c2的情况, x = c1*t1 + b1,x = c2*t…

2025 年 10 月天河区画册印刷,天河区印刷画册,天河区画册印刷设计,天河区画册印刷制作厂家最新推荐,聚焦资质、案例、售后的五家机构深度解读

引言 为助力天河区企业及个人精准选择画册印刷服务,本次推荐榜单由华南地区印刷行业协会联合第三方测评机构共同打造,测评周期为 2025 年 7 月 - 9 月,覆盖天河区 32 家画册印刷主流企业。测评采用 “三维九项” 评…

2025 年 10 月广州画册印刷制作,广州公司画册印刷,广州宣传画册印刷,广州画册印刷设计厂家最新推荐,聚焦资质、案例、售后的五家机构深度解读

引言 随着 2025 年广州画册印刷市场需求持续攀升,企业对画册印刷的品质、定制化程度及服务保障要求愈发严格。为帮助客户精准筛选优质合作方,本次测评由广州市印刷行业协会全程指导,联合第三方检测机构,从企业资质…

智能体来了:AI智能体就业培训的八大核心模块,开启未来职业新赛道

2025年,国务院〈人工智能+行动指南〉,文件中明确指出:到2027年,智能体普及率需超过70%;到2030年,超过90%。 这意味着“智能体(AI Agent)”已成为国家战略级新赛道,每一个人——无论是大学生、运营人、创业者…

本土化代码托管平台崛起:Gitee如何重塑国内开发者生态

本土化代码托管平台崛起:Gitee如何重塑国内开发者生态 在数字化转型浪潮下,代码托管平台已成为软件开发团队不可或缺的基础设施。随着国内开发者群体规模不断扩大,对本土化、合规化代码托管解决方案的需求日益凸显。…

2025年10月网上兼职赚钱正规平台推荐:高佣号卡分销排行榜

想找一份“时间自由、零成本启动、结算透明”的网上兼职,却常被“押金、拉人头、提现门槛”劝退?2025年,国家工信部持续收紧虚拟运营商牌照,正规号卡分销成为少数“零门槛、高合规”的线上副业赛道:无需囤货、无需…

2025年10月网上兼职赚钱正规平台推荐:高性价比榜单全解析

想找一份“足不出户、日结月清”的网上兼职,却担心遇到押金套路、提现门槛、信息泄露?2025年,人社部《灵活就业人员用工监测报告》显示,全国已有1.2亿灵活就业者,其中35%通过线上平台获取订单,但同期消协受理的“…

2025 年纸护角厂家最新推荐榜,技术实力与市场口碑深度解析防撞 / 加硬 / 蜂窝纸护角 / 纸护角厂家推荐

引言 为助力企业精准选择优质纸护角产品,本次推荐榜依托包装联合会 2024-2025 年度包装材料测评数据,结合行业权威检测机构 SGS 的性能测试报告综合制定。测评过程严格遵循 “三维九项” 评估体系:在技术维度,重点…

基于MATLAB的MIT-BIH ECG数据PQRST波定位实现

一、数据读取与预处理 1.1 MIT-BIH数据读取 % 读取头文件信息 header = read_header(100.hea); % 自定义函数解析.hea文件 fs = header.Fs; % 采样率(360Hz) gain = header.gain(1); % …

2025年10月网上兼职赚钱正规平台推荐:高性价比列表全解析

“想用手机在地铁里动动手指,月底就能多一笔收入”,这是很多人搜索“网上兼职赚钱正规平台”时的真实场景。可点开网页,满屏“日入五百”却说不清资质,注册后先交押金,提现时突然冒出“流水不足”,辛苦拉新的佣金…

ansible 模块

ansible 模块Ansible playbook 常用模块 service /systemd 模块 服务器状态 # service centos6 - name: restart XXXservice:name: iptables state: started/stoped/restarted/reloadedenabled:nowhen: ansible_os…

2025年10月烤火炉推荐:知名榜单全维度选择方案

霜降一过,长江中下游的湿冷开始往屋里钻,北方尚未供暖的“空窗期”也让客厅秒变冰窖。租住房东不让改燃气、有娃家庭怕明火、老人关节受不了空调直吹,这些真实场景把“烤火炉”推上热搜。奥维云网2024取暖季数据显示…

2025年10月烤火炉推荐:主流品牌口碑排行榜与避坑指南

一到十月,北方集中供暖尚未启动,南方湿冷已悄然来袭,不少家庭、租房族、银发人群开始把“烤火炉”加入紧急采购清单。调研机构奥维云网显示,2024年取暖季线上销量同比增27%,其中石墨烯速热品类占比首次突破35%,成…

【金融行业案例】基于Vaadin全栈Java框架重构内部系统,全面提升开发效率与用户体验

BCI银行通过采用Vaadin实现了从传统系统向现代化内部工具的全面转型,显著提升了开发速度与用户体验,也为全球金融行业的系统升级提供了参考范例。导读: 在数字化转型的浪潮中,非洲领先金融机构 BCI银行(Banco Com…

2025年10月烤火炉推荐:对比排行榜助你轻松选

一到深秋,南方湿冷与北方干冷同步上线,很多人下班回家的第一件事就是打开烤火炉。可市面上产品从百元小太阳到近三千元仿真壁炉,功率、发热体、安全保护、能耗、噪音、颜值差异巨大,用户最怕“买前心动、买后闲置”…

Web前端入门第 89 问:总结 8 种跨域通信处理方案

为什么会跨域?跨域是谁附加的限制?为什么 APP 不会有跨域问题? 首先跨域问题是由于浏览器的同源策略(Same-Origin Policy)导致的,基本上所有浏览器都有限制,默认情况是不允许跨域访问的!! APP 的请求不受浏览…

2025年10月中国办公家具定制公司推荐:评价排行榜与选购指南

正在升级办公环境的企业行政、采购或创业者,常面临“预算有限却想要品牌感”“工期紧张又怕环保不达标”“展厅看得眼花缭乱却找不到落地案例”的三重焦虑。2025年第三季度全国规模以上服务业景气指数显示,办公空间升…