onlyrsa
n在11进制下0特别多,放多项式里分解就行了。
分解后有一半不是素的,拿另一个大因子算就行了
n = 264048827496427248021277383801027180195275776366915828865010362454006394906519399441496561006668252031429735502465174250525698696973129422193405161920872162928097673289330345041221985548078586423910246601720647996170161319016119241836415788315729493164331517547663558380515400720081995290120793014108439083514403659082115510258023834737471488528527557960636984676435543300074504679264476413252780514962473070445293528877641502742438571110744667739728450283295649865745629276142949963507003094791773183928894536793857609738113546410753895719242547720815692998871947957214118354127328586542848234994500987288641595105
e = 65537
c = 76196483810925191371357319946893762223027002702624516192769497540954799651198719100683206759706879828894501526423422596543748404479640715319801018211652987852179907519286760601944889601355220646374788026632971331786307898234821477134265724962397355614076896148563340833323366935479885600112872998594315513803419069126624158092821269145991266528158747750965226483644012365861166608598063649804899693010576080857540523307078138634628539419178875838147396170651777949577793359622498517581948006585916952705460782942977789615065947303447566918741750017127110484065354974088489869377128636357092420660532261674969708694
from Crypto.Util.number import *
digits = n.digits(11)
f = 0
for i, each in enumerate(digits):
f += each * x ^ i
factors = f.factor_list()
p = factors[0][0]
q = factors[1][0]
p = p(x=11)
q = q(x=11)
assert p * q == n
if not is_prime(p):
p = q
d = inverse_mod(e, p - 1)
print(long_to_bytes(pow(c, d, p)))
ezhash
中间相遇攻击,尝试从前后分别构造消息块并往中间状态推导并等待碰撞,一旦碰撞说明找到了合适的构造方案。朴素算法时间复杂度为O(2^{40}),中间相遇只需要O(2^{20})
# -*- coding: utf-8 -*-
from Crypto.Cipher import AES
from Crypto.Util.number import *
from tqdm import trange
aes = AES.new(b"a"*32, AES.MODE_ECB)
last = b'\x03\x1c\xddf:\xa0\xea\xb1\xa5\x03\xe7>\x13\x0bL\xbf'
def pad(m):
padding_len = 11 - len(m) % 11
m += bytes([0x80] + [padding_len - 1] * (padding_len - 1))
return m + b'\x00' * 5
def solve(m1, m2):
m1 = long_to_bytes(m1).rjust(11, b'\x00') + b'\x00' * 5
m2 = pad(long_to_bytes(m2))
m1 = bytes([(each + 2) % 256 for each in m1])
m1 = aes.encrypt(m1)
m2 = bytes([(each2 - each1 - 2) % 256 for each1, each2 in zip(m2, last)])
m2 = aes.decrypt(m2)
mid = bytes([(each2 - each1 - 2) % 256 for each1, each2 in zip(m1, m2)])
assert mid[-5:] == b'\x00' * 5
return mid[:-5]
import string
charset = string.ascii_letters+string.digits
from hashlib import sha256
def proof(known, hashcode):
for each1 in charset:
for each2 in charset:
for each3 in charset:
for each4 in charset:
this = each1 + each2 + each3 + each4 + known
if sha256(this.encode()).hexdigest() == hashcode:
return this[:4]
middle = {}
left = []
right = []
data = 0
while True:
this = long_to_bytes(data).rjust(11, b'\x00') + b'\x00' * 5
this = bytes([(each + 2) % 256 for each in this])
this = aes.encrypt(this)[-5:]
this = bytes([(each + 2) % 256 for each in this])
if this not in middle:
middle[this] = data
left.append(this)
elif this not in left:
print(long_to_bytes(data).rjust(11, '\x00'))
print(solve(data, middle[this]))
print(long_to_bytes(middle[this]))
break
this = pad(long_to_bytes(data))
this = bytes([(each2 - each1 - 2) % 256 for each1, each2 in zip(this, last)])
this = aes.decrypt(this)[-5:]
if this not in middle:
middle[this] = data
right.append(this)
elif this not in right:
print(long_to_bytes(middle[this]).rjust(11, b'\x00'))
print(solve(middle[this], data))
print(long_to_bytes(data))
break
data += 1
输出的三行消息拼接起来就是碰撞
bad prince
prince加密算法的故障注入,题目中每次访问远程,注入的轮数是6、7、8三个值随机的。根据Aikata等人在《PRINCE under Differential Fault Attack: Now in 3D》中提到的解决方案得知,攻击第六轮的注入几乎是不可能的。因此如果链接远程拿了个第六轮注入的,寄,重开。
github上面可以找到这样一个项目:PRINCE-under-Differential-Fault-Attack-Now-in-3D-master,其中积分攻击部分实现了第七轮的故障注入密钥破解,并且条件符合题目情景。只需要把IntegralAttack.py中生成密文的部分去掉,换成题目中给的密文,就可以获取K1和K0-Prime,然后根据逻辑计算k0即可。
具体如何判断注入点是不是第七轮,根据上面paper描述,可以推导出:如果注入在第八轮,那么这些密文的异或值肯定为全0;然后根据GitHub项目,如果注入在第六轮,那么这个项目的代码无法分析注入位置。
# -*- coding: utf-8 -*-
from IntegralAttack import IntegralAttack
from bitstring import BitArray
from os import urandom
from Crypto.Util.number import long_to_bytes
from PRINCE import PRINCE
hint = ['981541862745d3a9', 'f745b43a26392642', 'cd86e761261ea7e9', 'c78b3a7547b8b950', '9c167a7dcdac0268', '5718b269685a3a3b', 'fe930d8ccb2df025', 'ff98c7ad820d6438', '801d1b0f5da07d98', '4a584c3f2a09c88e', '9d2da4929d88dbaa', 'ed5eaacaba82be29', 'cd7ee3a175a83ba1', 'd111a1965a7b08d2', '25e1156a45f70d07', 'ec078e2281df3d31']
enc_flag = "992c4e89dd8a69eaf552808da2b18a426d8f8c9e2e779c88d9f2aeab263f1ab07156e10e966bc069a4f34006cb8b1d76"
hint = [BitArray("0x" + each) for each in hint]
key = BitArray(urandom(16))
attacker = IntegralAttack(BitArray(b"\x00" * 8), key, faultyNibble = 15, c = hint)
#attacker.launch_attack(1)
k1 = 0x40454c5481c7c617
k0_prime=0x67d4e62803b8ee03
data2 = 0x2791aa7c827f2814
k0 = int("1100111110101001110011000101000000000111011100011101110000000100", 2)
key = (k0 << 64) + k1
key = BitArray(hex(key))
princeObj = PRINCE(key)
flag = b''
for i in range(0, len(enc_flag), 16):
this = princeObj.decrypt(BitArray("0x" + enc_flag[i:i+16])).hex
flag += long_to_bytes(int(this, 16))
print(flag)