RSA | ISCTF2024 | Crypto 我和小蓝鲨的秘密
2024年12月10日约 514 字大约 2 分钟
原题
from PIL import Image
from Crypto.Util.number import bytes_to_long, long_to_bytes
import numpy as np
n = 29869349657224745144762606999
e = 65537
original_image_path = "flag.jpg"
img = Image.open(original_image_path)
img = img.convert("RGB")
img_array = np.array(img)
h, w, _ = img_array.shape
encrypted_array = np.zeros((h, w, 3), dtype=object)
for i in range(h):
for j in range(w):
r, g, b = int(img_array[i, j, 0]), int(img_array[i, j, 1]), int(img_array[i, j, 2])
encrypted_array[i, j, 0] = pow(r, e, n)
encrypted_array[i, j, 1] = pow(g, e, n)
encrypted_array[i, j, 2] = pow(b, e, n)
np.save("encrypted_image.npy", encrypted_array)
print("图片已加密并保存为 encrypted_image.npy")
安装运行库
pip install pillow pycryptodome numpy sympy
代码分析
这段代码使用 RSA 加密算法对图片的每个像素进行加密,并将加密后的数据保存为一个 NumPy 数组文件。
计算私钥
既然是 RSA,那么就需要分解n
。所幸,这个n
非常的短。
n = 29869349657224745144762606999
e = 65537
那么我们可以直接将p
和q
给分解出来。
factors = list(sympy.factorint(n).keys())
p, q = factors[0], factors[1]
既然得到了p
和q
,我们可以把φ(n)
求出来。
phi_n = (p - 1) * (q - 1)
然后计算得到私钥d
.
d = pow(e, -1, phi_n)
解密图片
我们读取 Numpy 数组,逆向加密代码将各个像素点解密。
encrypted_array = np.load("encrypted_image.npy", allow_pickle=True)
h, w, _ = encrypted_array.shape
decrypted_array = np.zeros((h, w, 3), dtype=np.uint8)
for i in range(h):
for j in range(w):
r, g, b = int(encrypted_array[i, j, 0]), int(encrypted_array[i, j, 1]), int(encrypted_array[i, j, 2])
decrypted_array[i, j, 0] = pow(r, d, n)
decrypted_array[i, j, 1] = pow(g, d, n)
decrypted_array[i, j, 2] = pow(b, d, n)
然后将所有的数组转为图片并保存。
decrypted_img = Image.fromarray(decrypted_array, 'RGB')
decrypted_img.save("decrypted_flag.jpg")
完整代码实现
from PIL import Image
import numpy as np
import sympy
n = 29869349657224745144762606999
e = 65537
factors = list(sympy.factorint(n).keys())
p, q = factors[0], factors[1]
phi_n = (p - 1) * (q - 1)
d = pow(e, -1, phi_n)
encrypted_array = np.load("encrypted_image.npy", allow_pickle=True)
h, w, _ = encrypted_array.shape
decrypted_array = np.zeros((h, w, 3), dtype=np.uint8)
for i in range(h):
for j in range(w):
r, g, b = int(encrypted_array[i, j, 0]), int(encrypted_array[i, j, 1]), int(encrypted_array[i, j, 2])
decrypted_array[i, j, 0] = pow(r, d, n)
decrypted_array[i, j, 1] = pow(g, d, n)
decrypted_array[i, j, 2] = pow(b, d, n)
decrypted_img = Image.fromarray(decrypted_array, 'RGB')
decrypted_img.save("decrypted_flag.jpg")