https://arweave.net/) using the get
function, which repeatedly tries to download the file until it is successful. The file is then verified for integrity by checking its checksum against the expected value, and if the checksum is valid, the file is decrypted using the AES-GCM algorithm. The decryption key is derived from an initial seed key, which is passed through a key derivation function. The decrypted file is saved to the local file system using the filename
variable, which is specified in the code. If the debug
variable is set to True, the script will instead print the decrypted files without saving them to the file system.
import os
from base64 import urlsafe_b64decode
from hashlib import sha3_256, sha3_512
from json import loads
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
from requests.models import Response
from requests.sessions import Session
filename: str = r"A-001.Algha_Porthos.2020 年 9 月运动会.20210925.2e2ded26.7z"
debug: bool = False
class Seed:
key: bytes = urlsafe_b64decode(
b"qj9ENpsLjg3we3P2UNeAfCuRvhD33TWq0HiiAPx55paHiP41pOy0fui31qg55IQS7UbAsgvd2vvVZ_KJNbQClA=="
)
ar: str = "45lnefx-m-cQlzDSrtkBaPee9KkQKn7tTj9Iq8oTiU8"
checksum: str = "ucpRqnqj4PL3QtzFMOsz5qQZ-u95NPd_kqZvSkXAxSQ="
class KeyDerivation:
def __init__(self, iv: bytes, next: bytes) -> None:
assert len(iv) == 256, "iv must be 2048 bits"
assert len(next) == 64, "next must be 512 bits"
self.__generator__ = sha3_512(iv)
self.__next__ = next
def __call__(self) -> bytes:
self.__generator__.update(self.__generator__.digest())
self.__generator__.update(self.__next__)
return self.__generator__.digest()
def decrypt(data: bytes, key: bytes) -> bytes:
assert len(key) == 64, "key must be 512 bits"
return AESGCM(key=key[:32]).decrypt(
nonce=key[-12:], data=data, associated_data=key[32:-12]
)
session = Session()
def get(ar: str) -> Response:
print("ar", ar)
while True:
try:
resp = session.get(f"https://arweave.net/{ar}/d")
resp.raise_for_status()
return resp
except Exception as err:
print("error", err)
def extract(key: bytes, ar: str, checksum: str) -> bytes:
checksum = urlsafe_b64decode(checksum)
checked = False
while not checked:
data = get(ar).content[12:]
checked = checksum == (sha3_256(data).digest())
return decrypt(data=data, key=key)
if __name__ == "__main__":
seed = loads(extract(key=Seed.key, ar=Seed.ar, checksum=Seed.checksum))
keyDerivation = KeyDerivation(
iv=urlsafe_b64decode(seed["crypto"]["iv"]),
next=urlsafe_b64decode(seed["crypto"]["next"]),
)
print("debug", debug)
if debug:
for obj in seed["store"]:
key = keyDerivation()
extract(key=key, ar=obj["ar"], checksum=obj["checksum"])
else:
import sys
if getattr(sys, "frozen", False):
current = os.path.dirname(sys.executable)
else:
current = os.path.dirname(os.path.abspath(__file__))
with open(os.path.join(current, filename), "wb") as fout:
for obj in seed["store"]:
key = keyDerivation()
fout.write(extract(key=key, ar=obj["ar"], checksum=obj["checksum"]))