【已无】完成基于内存的PoW证明,赢得邀请码
- 内容介绍
- 文章标签
- 相关推荐
这次仍然是采用Argon2id算法,但加入了船新玩法!
游戏说明:守护人类的强大魔法水晶被邪恶的巨龙盗走。巨龙将水晶分成五块,散落在极北寒地、东部群峦、中部荒漠、西部草原和南部飓风五片大陆之中。勇敢又聪慧的你,危难时刻担起重任,只身前往这五片大陆寻找失落的水晶碎片,勇者的故事就此展开……
游戏玩法:总共有五个终极密钥碎片,你需要集齐至少任意三个终极密钥碎片,然后使用Shamir算法合成成一把完整的终极密钥作为AES128 ECB的密钥,解开邀请码密文的加密。
终极密钥碎片获得:你需要在指定的范围内找到一个数字,将该数字与题目中的“字符串前缀”拼接在一起(字符串前缀+数字)组成一个新的字符串。将新的字符串进行UTF-8编码并使用Argon2id算法进行计算(请勿修改题目提供的Argon2id参数,否则会永远无法得到正确答案)。得到的16字节(128位)作为AES128 ECB的Secret对终极密钥碎片密文进行解密,如果得到的内容包含指定特征,则代表你找到了正确的终极密钥碎片!
简而言之,就是你需要在五个范围内找到至少三个正确的数字,通过Argon2id算法生成出hash,将hash作为AES密钥通过AES将终极密钥碎片密文解密,拿到三个终极密钥碎片后使用Shamir算法合成终极密钥,然后再用AES解密邀请码密文
出题代码
import base64
import os
import argon2
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from Crypto.Protocol.SecretSharing import Shamir
kdf_prefix = "LinuxDo" # KDF派生密钥前缀
shamir_secret_prefix = "恭喜!这是密钥碎片:" # 特征
plain_text = "恭喜!你成功得到了邀请码:" # 邀请码,待定
# Argon2id 参数
time_cost = 2 # 循环2次
memory_cost = 65536 # 64MB 内存块
parallelism = 4 # 四线程计算
argon2_salt = b"" # argon2算法盐值,待定
k = 3 # 所需密钥碎片数
n = 5 # 总共密钥碎片数
nonces = [0, 0, 0, 0, 0] # nonce集合,与密钥总碎片数一致,待定
print("开始生成...\n")
master_aes_key = os.urandom(16) # AES 主密钥
print(f"已生成AES主密钥{master_aes_key.hex()}")
cipher = AES.new(master_aes_key, AES.MODE_ECB)
padded_plaintext = pad(plain_text.encode("utf-8"), AES.block_size)
ciphertext_bytes = cipher.encrypt(padded_plaintext)
ciphertext_base64 = base64.b64encode(ciphertext_bytes).decode("utf-8") # 密文
print("加密完成\n")
print(f"最终邀请码密文:{ciphertext_base64}")
print("切分密钥中...\n")
shares = Shamir.split(k, n, master_aes_key, False)
magic_shamir_secret_list = []
for idx, share_bytes in shares:
print(f"密钥碎片 {idx}: {share_bytes.hex()}")
magic_shamir_secret = shamir_secret_prefix + share_bytes.hex()
magic_shamir_secret_list.append(magic_shamir_secret)
for idx, nonce in enumerate(nonces, start=1):
nonce_text = str(nonce)
text_to_hash = (kdf_prefix + nonce_text).encode("utf-8")
magic_shamir_secret_aes_key_bytes = argon2.low_level.hash_secret_raw(
secret=text_to_hash,
salt=argon2_salt,
time_cost=time_cost,
memory_cost=memory_cost,
parallelism=parallelism,
hash_len=16,
type=argon2.low_level.Type.ID,
)
cipher = AES.new(magic_shamir_secret_aes_key_bytes, AES.MODE_ECB)
padded_plaintext = pad(
magic_shamir_secret_list[idx - 1].encode("utf-8"), AES.block_size
)
ciphertext_bytes = cipher.encrypt(padded_plaintext)
ciphertext_base64 = base64.b64encode(ciphertext_bytes).decode("utf-8")
print(f"密钥碎片 {idx}密文:{ciphertext_base64}")
解密代码参考
import base64
import argon2
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
import time
import random
kdf_prefix = "LinuxDo" # KDF派生密钥前缀
shamir_secret_prefix = "恭喜!这是密钥碎片:" # 密钥碎片特征
ciphertext_base64 = "" # 粘贴密钥密文碎片
MIN_RANGE = 0 # 粘贴最小范围
MAX_RANGE = 0 # 粘贴最大范围
# Argon2id 参数
time_cost = 2 # 循环2次
memory_cost = 65536 # 64MB 内存块
parallelism = 4 # 四线程计算
argon2_salt = b"" # 粘贴argon2算法盐值
print("开始验证...")
start_time = time.time()
ciphertext_bytes = base64.b64decode(ciphertext_base64)
tested_nonces = set()
while True:
if len(tested_nonces) > MAX_RANGE - MIN_RANGE:
print("卡池已抽干,未能找到正确钥匙!") # 按理说应该是不会哈
break
nonce = random.randint(MIN_RANGE, MAX_RANGE)
if nonce in tested_nonces:
continue
tested_nonces.add(nonce)
nonce_text = str(nonce)
text_to_hash = (kdf_prefix + nonce_text).encode("utf-8")
magic_shamir_secret_aes_key_bytes = argon2.low_level.hash_secret_raw(
secret=text_to_hash,
salt=argon2_salt,
time_cost=time_cost,
memory_cost=memory_cost,
parallelism=parallelism,
hash_len=16,
type=argon2.low_level.Type.ID,
)
try:
cipher = AES.new(magic_shamir_secret_aes_key_bytes, AES.MODE_ECB)
decrypted_padded = cipher.decrypt(ciphertext_bytes)
decrypted_text = unpad(decrypted_padded, AES.block_size).decode("utf-8")
if shamir_secret_prefix in decrypted_text:
elapsed = time.time() - start_time
print(f"\n🌟 恭喜找到一枚密钥碎片,耗时 {elapsed:.2f} 秒")
print(f"🌟 你一共抽了 {len(tested_nonces)} 次卡!")
print(f"✅ 正确的nonce 是: {nonce_text}")
print(f"🎉 明文是: \n{decrypted_text}")
break
except Exception:
pass
tries = len(tested_nonces)
if tries > 0 and tries % 50 == 0:
print(f"[*] 进度:已进行 {tries} 次抽卡...")
合成终极密钥代码参考
import base64
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
from Crypto.Protocol.SecretSharing import Shamir
magic_shamir_secret_list = [
"",
"",
"",
"",
"",
] # 粘贴密钥碎片(有顺序要求!)
shamir_secrets = []
ciphertext_base64 = "" # 粘贴邀请码密文
for idx, secret_text in enumerate(magic_shamir_secret_list, start=1):
if secret_text == "":
continue
secret_bytes = bytes.fromhex(secret_text)
shamir_secrets.append((idx, secret_bytes))
master_key = Shamir.combine(shamir_secrets, ssss=False)
cipher_main = AES.new(master_key, AES.MODE_ECB)
master_bytes = base64.b64decode(ciphertext_base64)
decrypted_msg = unpad(cipher_main.decrypt(master_bytes), AES.block_size).decode("utf-8")
print(f"🏆 最终结果:{decrypted_msg}")
需要注意的是,“特征”字符串不是密钥的一部分!另外终极密钥碎片合并时是由顺序要求的,顺序不要填错了。每个“大陆”范围为十万
游戏参数:
KDF派生密钥前缀:LinuxDo
特征:恭喜!这是密钥碎片:
邀请码密文:0OSVw5qywpzm5Kqir5zp+zG9v5SE6Ajd9g4enijnCdvH50rcS8vjSXcLSk0Xl0VbkFM1g+0KvGmgAbjc0s6YwQ==
终极密钥碎片密文与范围:
A:PPHJKZlof61lxDS707ZJQXvhWEby57BRKRQp3wdjIgQ1q8kK5DFbNOgZkJBT5AVm9xiqakUz+rNRX5AKiruplQ== 0-100000
B:iRDm+IG9hGljT6WxvO4HlkMphrz5Ynx/QazeNlHC1fzqwJryCUBlg0tBQwyJ+7ezfaeukjLkDsYU3xUQH6LQsQ== 730000-830000
C:uPFGqYsFUqpzJqEF3OULH3exY5lOC60apAsb6jUstQgR68SkSSS6SN596R84hko6RTiMtGtItIvEgnIbP+r5ow== 9320000-9420000
D:2e98v1h2pVz8ZajPlwMuAkRNnRymoxweB7mE3A1kiodDCTgoWrSDw3SVL8tAZ+IQMNBa3QWx8Ti2iTVmg5hk4g== 83600000-83700000
E:tz1xhHtIFCzvJWtnWA3OqxPRb9KVP2iURqOPL0or3AYAaVuBAutSTHmtN/mjHGs75rhFMKQ1MDM98oWauPV/yw== 784700000-784800000
argon2算法盐值:d4uUFb3SQbwqSXCAQk7P@tSFSMg7gC3p
Argon2id循环次数:2
Argon2id内存消耗:64MB
线程:4
“Fairer. More fun. And all about luck.”
网友解答:--【壹】--:
恭喜!!!
--【贰】--:
不难吧qwq
--【叁】--:
???这么难
--【肆】--:
拿下拿下
--【伍】--:
wwww!
这次仍然是采用Argon2id算法,但加入了船新玩法!
游戏说明:守护人类的强大魔法水晶被邪恶的巨龙盗走。巨龙将水晶分成五块,散落在极北寒地、东部群峦、中部荒漠、西部草原和南部飓风五片大陆之中。勇敢又聪慧的你,危难时刻担起重任,只身前往这五片大陆寻找失落的水晶碎片,勇者的故事就此展开……
游戏玩法:总共有五个终极密钥碎片,你需要集齐至少任意三个终极密钥碎片,然后使用Shamir算法合成成一把完整的终极密钥作为AES128 ECB的密钥,解开邀请码密文的加密。
终极密钥碎片获得:你需要在指定的范围内找到一个数字,将该数字与题目中的“字符串前缀”拼接在一起(字符串前缀+数字)组成一个新的字符串。将新的字符串进行UTF-8编码并使用Argon2id算法进行计算(请勿修改题目提供的Argon2id参数,否则会永远无法得到正确答案)。得到的16字节(128位)作为AES128 ECB的Secret对终极密钥碎片密文进行解密,如果得到的内容包含指定特征,则代表你找到了正确的终极密钥碎片!
简而言之,就是你需要在五个范围内找到至少三个正确的数字,通过Argon2id算法生成出hash,将hash作为AES密钥通过AES将终极密钥碎片密文解密,拿到三个终极密钥碎片后使用Shamir算法合成终极密钥,然后再用AES解密邀请码密文
出题代码
import base64
import os
import argon2
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from Crypto.Protocol.SecretSharing import Shamir
kdf_prefix = "LinuxDo" # KDF派生密钥前缀
shamir_secret_prefix = "恭喜!这是密钥碎片:" # 特征
plain_text = "恭喜!你成功得到了邀请码:" # 邀请码,待定
# Argon2id 参数
time_cost = 2 # 循环2次
memory_cost = 65536 # 64MB 内存块
parallelism = 4 # 四线程计算
argon2_salt = b"" # argon2算法盐值,待定
k = 3 # 所需密钥碎片数
n = 5 # 总共密钥碎片数
nonces = [0, 0, 0, 0, 0] # nonce集合,与密钥总碎片数一致,待定
print("开始生成...\n")
master_aes_key = os.urandom(16) # AES 主密钥
print(f"已生成AES主密钥{master_aes_key.hex()}")
cipher = AES.new(master_aes_key, AES.MODE_ECB)
padded_plaintext = pad(plain_text.encode("utf-8"), AES.block_size)
ciphertext_bytes = cipher.encrypt(padded_plaintext)
ciphertext_base64 = base64.b64encode(ciphertext_bytes).decode("utf-8") # 密文
print("加密完成\n")
print(f"最终邀请码密文:{ciphertext_base64}")
print("切分密钥中...\n")
shares = Shamir.split(k, n, master_aes_key, False)
magic_shamir_secret_list = []
for idx, share_bytes in shares:
print(f"密钥碎片 {idx}: {share_bytes.hex()}")
magic_shamir_secret = shamir_secret_prefix + share_bytes.hex()
magic_shamir_secret_list.append(magic_shamir_secret)
for idx, nonce in enumerate(nonces, start=1):
nonce_text = str(nonce)
text_to_hash = (kdf_prefix + nonce_text).encode("utf-8")
magic_shamir_secret_aes_key_bytes = argon2.low_level.hash_secret_raw(
secret=text_to_hash,
salt=argon2_salt,
time_cost=time_cost,
memory_cost=memory_cost,
parallelism=parallelism,
hash_len=16,
type=argon2.low_level.Type.ID,
)
cipher = AES.new(magic_shamir_secret_aes_key_bytes, AES.MODE_ECB)
padded_plaintext = pad(
magic_shamir_secret_list[idx - 1].encode("utf-8"), AES.block_size
)
ciphertext_bytes = cipher.encrypt(padded_plaintext)
ciphertext_base64 = base64.b64encode(ciphertext_bytes).decode("utf-8")
print(f"密钥碎片 {idx}密文:{ciphertext_base64}")
解密代码参考
import base64
import argon2
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
import time
import random
kdf_prefix = "LinuxDo" # KDF派生密钥前缀
shamir_secret_prefix = "恭喜!这是密钥碎片:" # 密钥碎片特征
ciphertext_base64 = "" # 粘贴密钥密文碎片
MIN_RANGE = 0 # 粘贴最小范围
MAX_RANGE = 0 # 粘贴最大范围
# Argon2id 参数
time_cost = 2 # 循环2次
memory_cost = 65536 # 64MB 内存块
parallelism = 4 # 四线程计算
argon2_salt = b"" # 粘贴argon2算法盐值
print("开始验证...")
start_time = time.time()
ciphertext_bytes = base64.b64decode(ciphertext_base64)
tested_nonces = set()
while True:
if len(tested_nonces) > MAX_RANGE - MIN_RANGE:
print("卡池已抽干,未能找到正确钥匙!") # 按理说应该是不会哈
break
nonce = random.randint(MIN_RANGE, MAX_RANGE)
if nonce in tested_nonces:
continue
tested_nonces.add(nonce)
nonce_text = str(nonce)
text_to_hash = (kdf_prefix + nonce_text).encode("utf-8")
magic_shamir_secret_aes_key_bytes = argon2.low_level.hash_secret_raw(
secret=text_to_hash,
salt=argon2_salt,
time_cost=time_cost,
memory_cost=memory_cost,
parallelism=parallelism,
hash_len=16,
type=argon2.low_level.Type.ID,
)
try:
cipher = AES.new(magic_shamir_secret_aes_key_bytes, AES.MODE_ECB)
decrypted_padded = cipher.decrypt(ciphertext_bytes)
decrypted_text = unpad(decrypted_padded, AES.block_size).decode("utf-8")
if shamir_secret_prefix in decrypted_text:
elapsed = time.time() - start_time
print(f"\n🌟 恭喜找到一枚密钥碎片,耗时 {elapsed:.2f} 秒")
print(f"🌟 你一共抽了 {len(tested_nonces)} 次卡!")
print(f"✅ 正确的nonce 是: {nonce_text}")
print(f"🎉 明文是: \n{decrypted_text}")
break
except Exception:
pass
tries = len(tested_nonces)
if tries > 0 and tries % 50 == 0:
print(f"[*] 进度:已进行 {tries} 次抽卡...")
合成终极密钥代码参考
import base64
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
from Crypto.Protocol.SecretSharing import Shamir
magic_shamir_secret_list = [
"",
"",
"",
"",
"",
] # 粘贴密钥碎片(有顺序要求!)
shamir_secrets = []
ciphertext_base64 = "" # 粘贴邀请码密文
for idx, secret_text in enumerate(magic_shamir_secret_list, start=1):
if secret_text == "":
continue
secret_bytes = bytes.fromhex(secret_text)
shamir_secrets.append((idx, secret_bytes))
master_key = Shamir.combine(shamir_secrets, ssss=False)
cipher_main = AES.new(master_key, AES.MODE_ECB)
master_bytes = base64.b64decode(ciphertext_base64)
decrypted_msg = unpad(cipher_main.decrypt(master_bytes), AES.block_size).decode("utf-8")
print(f"🏆 最终结果:{decrypted_msg}")
需要注意的是,“特征”字符串不是密钥的一部分!另外终极密钥碎片合并时是由顺序要求的,顺序不要填错了。每个“大陆”范围为十万
游戏参数:
KDF派生密钥前缀:LinuxDo
特征:恭喜!这是密钥碎片:
邀请码密文:0OSVw5qywpzm5Kqir5zp+zG9v5SE6Ajd9g4enijnCdvH50rcS8vjSXcLSk0Xl0VbkFM1g+0KvGmgAbjc0s6YwQ==
终极密钥碎片密文与范围:
A:PPHJKZlof61lxDS707ZJQXvhWEby57BRKRQp3wdjIgQ1q8kK5DFbNOgZkJBT5AVm9xiqakUz+rNRX5AKiruplQ== 0-100000
B:iRDm+IG9hGljT6WxvO4HlkMphrz5Ynx/QazeNlHC1fzqwJryCUBlg0tBQwyJ+7ezfaeukjLkDsYU3xUQH6LQsQ== 730000-830000
C:uPFGqYsFUqpzJqEF3OULH3exY5lOC60apAsb6jUstQgR68SkSSS6SN596R84hko6RTiMtGtItIvEgnIbP+r5ow== 9320000-9420000
D:2e98v1h2pVz8ZajPlwMuAkRNnRymoxweB7mE3A1kiodDCTgoWrSDw3SVL8tAZ+IQMNBa3QWx8Ti2iTVmg5hk4g== 83600000-83700000
E:tz1xhHtIFCzvJWtnWA3OqxPRb9KVP2iURqOPL0or3AYAaVuBAutSTHmtN/mjHGs75rhFMKQ1MDM98oWauPV/yw== 784700000-784800000
argon2算法盐值:d4uUFb3SQbwqSXCAQk7P@tSFSMg7gC3p
Argon2id循环次数:2
Argon2id内存消耗:64MB
线程:4
“Fairer. More fun. And all about luck.”
网友解答:--【壹】--:
恭喜!!!
--【贰】--:
不难吧qwq
--【叁】--:
???这么难
--【肆】--:
拿下拿下
--【伍】--:
wwww!

