# Cryptography 密码学
# 古典密码
# Rabbit 密码
需要一个密码,解密一个类似 base64 的
BITSCTF2025: The most wanted lagomorph
BITSCTF{f3rb_1_kn0w_wh47_w3_4r3_60nn4_d0_70d4y} |
加密 key=dennis
,变成
U2FsdGVkX1+Kci2LQvPTy06ga66qMTDgoOip6SxH1t7EreImxWCP3RarTyRTU2k3Nrd4vChzcXYKqPZSyl3T |
# 梅森旋转算法
python 里的 random
, C++ 里的 std::mt19937
都是这个算法,梅森旋转算法(Mersenne Twister Algorithm,简称 MT)
如果知道若干个连续生成的随机数,就可预测下一个
# mersenne-twister-predictor
使用 mt19937predictor
这个 python 包
先 pip 安装
pip install mersenne-twister-predictor |
使用:
import random | |
from mt19937predictor import MT19937Predictor | |
predictor = MT19937Predictor() | |
for _ in range(624): | |
x = random.getrandbits(32) | |
predictor.setrandbits(x, 32) # Submit samples here | |
# When enough samples are given, you can start predicting: | |
assert random.getrandbits(32) == predictor.getrandbits(32) |
# AES-CBC
# Decryption Oracle
# 得到 IV
在 AES 的 CBC 模式下,如果有 Decryption Oracle,那么可以得到 IV 的值,
参考:https://cedricvanrompay.gitlab.io/cryptopals/challenges/27.html
首先发送 3 个 block,
其中 , 那么解密得到的第一个是 , 第三个是 然后它们异或一下就可以了
Python 例子
from Crypto.Cipher import AES | |
from Crypto.Util.Padding import pad, unpad | |
def xor(a,b): | |
return bytearray([x ^ y for (x,y) in zip(a,b)]) | |
key = b"A" * 16 | |
iv = b"B" * 16 | |
print(f"{iv.hex() = }") | |
cipher = AES.new(key, AES.MODE_CBC, iv) | |
ciphertext = cipher.encrypt(pad((b"C" * 16) * 3, AES.block_size)) | |
cipher = AES.new(key, AES.MODE_CBC, iv) | |
plaintext = cipher.decrypt(ciphertext[:16] + (b"\x00" * 16) + ciphertext) | |
iv = xor(plaintext[:16], plaintext[32:48]) | |
print(f"{iv.hex() = }") # iv.hex() = '42424242424242424242424242424242' |
# RSA
首先生成 两个大质数,计算
然后选择 作为公钥,计算
是私钥
# 加密
对于 message
# 解密
对于 ciphertext
正确性:
# 结论
# 可枚举 z
所以
这个 在 之间
BITSCTF2025 Noob RSA returns
# ECDSA
全称是 Elliptic Curve Digital Signature Algorithm.
在椭圆曲线
其中
密钥包括私钥和公钥 私钥是 公钥是
是 的整数,
# 签名
输入消息 , 计算 , 随机生成 然后计算
签名是
# 验证签名
已知 先计算
然后计算
如果 和 一样,那么签名合法
# Python 库 ecdsa
首先
pip install ecdsa |
签名和验证
import ecdsa | |
from hashlib import sha256 | |
import random | |
private_key = ecdsa.SigningKey.generate(curve=ecdsa.SECP256k1, hashfunc=sha256) | |
dA = private_key.privkey.secret_multiplier | |
public_key = private_key.verifying_key | |
print(dA) # 打印 k | |
print(public_key.pubkey.point.to_bytes()) # 得到点 | |
k = random.randint(1, ecdsa.SECP256k1.order - 1) | |
signature = private_key.sign(b"First msg",hashfunc=sha256 ,k=k) | |
vk = private_key.get_verifying_key() | |
sig = private_key.sign(b"Hello msg") | |
vk.verify(sig, b"Hello msg") | |
vk.verify(signature, b"First msg") # 如果报错说明验证错误 | |
# 手动签名 1: | |
priv_key = ecdsa.SigningKey.from_secret_exponent(dA, curve=ecdsa.SECP256k1) | |
priv_key.sign(b"Hello msg",k=12) | |
print(sig) | |
# 得到 r,s | |
r = int.from_bytes(sig[:32]) | |
s = int.from_bytes(sig[32:]) | |
z = int.from_bytes(sha256(b"Hello msg").digest()) % ecdsa.SECP256k1.order |