mirror of
https://github.com/AkaiiKitsune/nijiiro-toolset.git
synced 2024-11-27 22:50:48 +01:00
135 lines
3.8 KiB
Python
135 lines
3.8 KiB
Python
import gzip
|
|
import os
|
|
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
|
|
from cryptography.hazmat.backends import default_backend
|
|
from cryptography.hazmat.primitives import padding
|
|
from argparse import ArgumentParser
|
|
from enum import Enum
|
|
import binascii
|
|
|
|
|
|
class Keys(Enum):
|
|
Datatable = "" # Add datatable key here
|
|
Fumen = "" # Add Fumen key here
|
|
|
|
|
|
def read_iv_from_file(file_path):
|
|
with open(file_path, "rb") as f:
|
|
iv = f.read(16)
|
|
if len(iv) != 16:
|
|
raise Exception("Invalid file")
|
|
return iv
|
|
|
|
|
|
def pad_data(data):
|
|
padder = padding.PKCS7(128).padder()
|
|
return padder.update(data) + padder.finalize()
|
|
|
|
|
|
def remove_pkcs7_padding(data):
|
|
unpadder = padding.PKCS7(128).unpadder()
|
|
return unpadder.update(data) + unpadder.finalize()
|
|
|
|
|
|
def decrypt_file(input_file, key_type: Keys = Keys(Keys.Datatable)):
|
|
# Convert the key from hex to bytes
|
|
key = binascii.unhexlify(Keys(key_type.value).value)
|
|
|
|
# Read the IV from the first 16 bytes of the input file
|
|
iv = read_iv_from_file(input_file)
|
|
|
|
# Create an AES cipher object with CBC mode
|
|
cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
|
|
decryptor = cipher.decryptor()
|
|
|
|
with open(input_file, "rb") as infile:
|
|
# Skip the IV in the input file
|
|
infile.seek(16)
|
|
|
|
# Decrypt the file
|
|
decrypted_data = b"" + decryptor.update(infile.read())
|
|
|
|
# Remove PKCS7 padding
|
|
unpadded_data = remove_pkcs7_padding(decrypted_data)
|
|
|
|
# Gzip decompress the data
|
|
decompressed_data = gzip.decompress(unpadded_data)
|
|
|
|
# return the decompressed data
|
|
return decompressed_data.decode()
|
|
|
|
|
|
def encrypt_file(input_file, key_type: Keys = Keys(Keys.Datatable)):
|
|
# Convert the key from hex to bytes
|
|
key = binascii.unhexlify(Keys(key_type.value).value)
|
|
|
|
# Generate a random 128-bit IV
|
|
iv = os.urandom(16)
|
|
|
|
# Create an AES cipher object with CBC mode
|
|
cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
|
|
encryptor = cipher.encryptor()
|
|
|
|
with open(input_file, "rb") as infile:
|
|
# Read the entire file into memory
|
|
data = infile.read()
|
|
|
|
# Gzip compress the data
|
|
compressed_data = gzip.compress(data)
|
|
|
|
# Pad the compressed data, encrypt it, and return the encrypted result
|
|
encrypted_data = (
|
|
encryptor.update(pad_data(compressed_data)) + encryptor.finalize()
|
|
)
|
|
|
|
return iv + encrypted_data
|
|
|
|
|
|
if __name__ == "__main__":
|
|
parser = ArgumentParser()
|
|
parser.add_argument(
|
|
"-i",
|
|
"--input",
|
|
help="Input file",
|
|
)
|
|
parser.add_argument(
|
|
"-o",
|
|
"--output",
|
|
help="Output file",
|
|
)
|
|
parser.add_argument(
|
|
"-e",
|
|
"--enc",
|
|
action="store_true",
|
|
default=False,
|
|
help="Use this flag to encrypt a file",
|
|
)
|
|
parser.add_argument(
|
|
"-t",
|
|
"--type",
|
|
default="Datatable",
|
|
help="Datatable is default, you can also use Fumen",
|
|
)
|
|
args = parser.parse_args()
|
|
|
|
if not args.input:
|
|
print("Missing input file, pass the argument --help for help")
|
|
exit(0)
|
|
|
|
if not args.output:
|
|
print("Missing output file, pass the argument --help for help")
|
|
exit(0)
|
|
|
|
type = Keys.Datatable if args.type == "Datatable" else Keys.Fumen
|
|
|
|
if not args.enc:
|
|
print("Encrypting " + args.input + " to " + args.output)
|
|
file = decrypt_file(input_file=args.input, key_type=type)
|
|
with open(args.output, "w") as outfile:
|
|
outfile.write(file)
|
|
else:
|
|
print("Decrypting " + args.input + " to " + args.output)
|
|
file = encrypt_file(input_file=args.input, key_type=type)
|
|
with open(args.output, "wb") as outfile:
|
|
outfile.write(file)
|