Reed-solomon testing and btc wallet generator.
This commit is contained in:
		
							
								
								
									
										74
									
								
								btc_wallets/Generate_btc_wallet_kdbx.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										74
									
								
								btc_wallets/Generate_btc_wallet_kdbx.py
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,74 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
 | 
			
		||||
import os
 | 
			
		||||
import qrcode
 | 
			
		||||
import base64
 | 
			
		||||
from mnemonic import Mnemonic
 | 
			
		||||
from bitcoinlib.keys import HDKey
 | 
			
		||||
from pykeepass import PyKeePass, create_database
 | 
			
		||||
from getpass import getpass
 | 
			
		||||
import gc
 | 
			
		||||
 | 
			
		||||
# Generate a BIP-0039 mnemonic seed phrase
 | 
			
		||||
mnemonic = Mnemonic("english")
 | 
			
		||||
seed_phrase = mnemonic.generate(strength=128)
 | 
			
		||||
 | 
			
		||||
# Derive the HDKey from the seed phrase
 | 
			
		||||
hd_key = HDKey.from_passphrase(seed_phrase)
 | 
			
		||||
 | 
			
		||||
# Derive the Bitcoin address from the HDKey
 | 
			
		||||
child_key = hd_key.subkey_for_path("m/0/0")
 | 
			
		||||
address = child_key.address()
 | 
			
		||||
 | 
			
		||||
# Create a QR code instance
 | 
			
		||||
qr = qrcode.QRCode(
 | 
			
		||||
    version=1,
 | 
			
		||||
    error_correction=qrcode.constants.ERROR_CORRECT_H,
 | 
			
		||||
    box_size=10,
 | 
			
		||||
    border=4,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
# Add the data to the QR code
 | 
			
		||||
qr.add_data(seed_phrase)
 | 
			
		||||
 | 
			
		||||
# Generate the QR code image
 | 
			
		||||
qr.make(fit=True)
 | 
			
		||||
qr_image = qr.make_image(fill_color="black", back_color="white")
 | 
			
		||||
 | 
			
		||||
# Convert the QR code image to base64
 | 
			
		||||
qr_base64 = base64.b64encode(qr_image.tobytes()).decode()
 | 
			
		||||
 | 
			
		||||
# Prompt for custom name for the wallet
 | 
			
		||||
wallet_name = input(
 | 
			
		||||
    "Whould you like to name this wallet? (empty for using the address as name): "
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
# Prompt the user for the passphrase
 | 
			
		||||
passphrase = getpass("Enter passphrase for the KeePassXC database: ")
 | 
			
		||||
 | 
			
		||||
# Create the database filename with the wallet number
 | 
			
		||||
if wallet_name == "":
 | 
			
		||||
    wallet_name = address
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
db_filename = f"{wallet_name}.kdbx"
 | 
			
		||||
 | 
			
		||||
# Create a KeePassXC database file
 | 
			
		||||
db = create_database(db_filename, password=passphrase)
 | 
			
		||||
 | 
			
		||||
# Create an entry in the root group
 | 
			
		||||
entry = db.add_entry(db.root_group, wallet_name, username=address, password=seed_phrase)
 | 
			
		||||
 | 
			
		||||
# Add the QR code as a note (base64 encoded)
 | 
			
		||||
entry.notes = qr_base64
 | 
			
		||||
 | 
			
		||||
# Save the database
 | 
			
		||||
db.save()
 | 
			
		||||
 | 
			
		||||
del mnemonic
 | 
			
		||||
del seed_phrase, address, hd_key, passphrase, qr_image, qr_base64
 | 
			
		||||
gc.collect()
 | 
			
		||||
 | 
			
		||||
print("---")
 | 
			
		||||
print("Bitcoin address was successfully created. You can find at: " + db_filename)
 | 
			
		||||
print("---")
 | 
			
		||||
@@ -1 +1 @@
 | 
			
		||||
ed566cf8f839c936bfd5582f1af6aa7d0d8457fcdd3c421d4424eedb41d5868155a6e04a291c4add0a2ec88a287d0371605d8ff9be6cbf2ba91d67097e39c0333cbf57515d9072d998d1dee110f3ecab
 | 
			
		||||
e71ad7d7815eef99ea4545da4ea22e9977c10c62c8e57cc794228e553c44e22f80cf5733aa00a53b6794b1e2732ab093eb63914155137988e58f8906acc5b57d02a981a2320a5b72a99ceaa5b68e2401
 | 
			
		||||
@@ -5,7 +5,8 @@ from data.data import add_data, save_data, set_encryption_key
 | 
			
		||||
 | 
			
		||||
def upload_and_store(data: Dict):
 | 
			
		||||
    # set encryption key if necessary
 | 
			
		||||
    set_encryption_key(b'upload_id=upload_and_store(my_da')
 | 
			
		||||
    my_key = b'upload_id=upload_and_store(my_da'
 | 
			
		||||
    set_encryption_key(my_key)
 | 
			
		||||
 | 
			
		||||
    traces = {}
 | 
			
		||||
    for service in [pastie, dpaste, rentry, defau, sprunge, opendev]:
 | 
			
		||||
@@ -13,11 +14,13 @@ def upload_and_store(data: Dict):
 | 
			
		||||
        if result:
 | 
			
		||||
            traces[result['name']] = result['key']
 | 
			
		||||
            add_data(service.get_service_tag(), result['name'], result['md5sum'])
 | 
			
		||||
    save_data('data.json', data, key=b'my_key123')
 | 
			
		||||
    save_data('data.json', data, key=my_key)
 | 
			
		||||
    return traces
 | 
			
		||||
 | 
			
		||||
my_data = {"name": "Sashenka", "age": 26, "country": "Anguilla"}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
upload_trace = upload_and_store(my_data)
 | 
			
		||||
 | 
			
		||||
print('trace: ', upload_trace)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								pastedb/solomon/cat.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								pastedb/solomon/cat.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 6.9 MiB  | 
							
								
								
									
										1
									
								
								pastedb/solomon/my_key.key
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								pastedb/solomon/my_key.key
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
f96404341e07a433c8e46612c16cd311de6f63cecc98bb6c799c1c79178bbfec3c07d106f3ff7426b39bb9fcc63c7d03533b9494f54bfa015240cbfdf3ea2274
 | 
			
		||||
							
								
								
									
										138
									
								
								pastedb/solomon/solomon-aes-tesing.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										138
									
								
								pastedb/solomon/solomon-aes-tesing.py
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,138 @@
 | 
			
		||||
import reedsolo
 | 
			
		||||
from Cryptodome.Cipher import AES
 | 
			
		||||
from Cryptodome.Random import get_random_bytes
 | 
			
		||||
from Cryptodome.Protocol.KDF import scrypt
 | 
			
		||||
from Cryptodome.Util.Padding import pad
 | 
			
		||||
 | 
			
		||||
# Parameters for key derivation function (KDF)
 | 
			
		||||
KDF_SALT = b"salt_for_key_derivation"
 | 
			
		||||
KDF_N = 2 ** 14  # CPU/memory cost parameter for scrypt KDF
 | 
			
		||||
KDF_r = 8  # Block size parameter for scrypt KDF
 | 
			
		||||
KDF_p = 1  # Parallelization parameter for scrypt KDF
 | 
			
		||||
KDF_KEY_LEN = 32  # Length of derived encryption key
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def encrypt_data(data, number, password=None, keyfile=None):
 | 
			
		||||
    """
 | 
			
		||||
    Encrypts data using Reed-Solomon coding and AES encryption.
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        data (bytes): The data to encrypt.
 | 
			
		||||
        number (int): The number of pieces to split the data into using Reed-Solomon coding.
 | 
			
		||||
        password (bytes or None): The password to use for key derivation using the scrypt KDF. If None,
 | 
			
		||||
            the key is read from the file specified by keyfile.
 | 
			
		||||
        keyfile (str or None): The path to the file containing the encryption key. If None, the key
 | 
			
		||||
            is derived from the password using the scrypt KDF.
 | 
			
		||||
    Returns:
 | 
			
		||||
        A list of bytes objects, each of which is an encrypted piece of the input data.
 | 
			
		||||
    Raises:
 | 
			
		||||
        ValueError: If the data cannot be split into the requested number of pieces using Reed-Solomon
 | 
			
		||||
            coding, or if an error occurs during key derivation.
 | 
			
		||||
    """
 | 
			
		||||
    # Use Reed-Solomon to split data into number pieces
 | 
			
		||||
    reed_rs = reedsolo.RSCodec(number)
 | 
			
		||||
    try:
 | 
			
		||||
        data_pieces = reed_rs.encode(data)
 | 
			
		||||
    except reedsolo.ReedSolomonError as reed_error:
 | 
			
		||||
        raise ValueError("Error during Reed-Solomon encoding: {}".format(str(reed_error)))
 | 
			
		||||
 | 
			
		||||
    # Derive encryption key from password using scrypt KDF, or read from file if specified
 | 
			
		||||
    if keyfile is None:
 | 
			
		||||
        try:
 | 
			
		||||
            key = scrypt(password, KDF_SALT, KDF_KEY_LEN, N=KDF_N, r=KDF_r, p=KDF_p)
 | 
			
		||||
        except ValueError as reed_error:
 | 
			
		||||
            raise ValueError("Error during key derivation: {}".format(str(reed_error)))
 | 
			
		||||
    else:
 | 
			
		||||
        key = read_key_from_file(keyfile)
 | 
			
		||||
 | 
			
		||||
    # Encrypt each piece using AES in GCM mode with derived key
 | 
			
		||||
    encrypted_pieces = []
 | 
			
		||||
    for piece in data_pieces:
 | 
			
		||||
        aes = AES.new(key, AES.MODE_GCM, nonce=get_random_bytes(12))
 | 
			
		||||
        ciphertext, tag = aes.encrypt_and_digest(pad(piece, AES.block_size))
 | 
			
		||||
        encrypted_pieces.append(ciphertext)
 | 
			
		||||
 | 
			
		||||
    return encrypted_pieces
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def read_key_from_file(keyfile):
 | 
			
		||||
    """
 | 
			
		||||
    Reads an encryption key from a file.
 | 
			
		||||
    Args:
 | 
			
		||||
        keyfile (str): The path to the file containing the encryption key.
 | 
			
		||||
    Returns:
 | 
			
		||||
        A bytes object containing the encryption key.
 | 
			
		||||
    Raises:
 | 
			
		||||
        ValueError: If the key file does not exist or the key length is invalid.
 | 
			
		||||
    """
 | 
			
		||||
    with open(keyfile, "rb") as key_file:
 | 
			
		||||
        key = key_file.read().strip()
 | 
			
		||||
    if len(key) != KDF_KEY_LEN:
 | 
			
		||||
        raise ValueError("Invalid key length")
 | 
			
		||||
    return key
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def decrypt_data(data_pieces, key, keyfile=None, password=None):
 | 
			
		||||
    """
 | 
			
		||||
    Decrypts a list of encrypted data pieces using AES in CBC mode with PKCS7 padding,
 | 
			
		||||
    and returns the original data by reassembling the pieces using Reed-Solomon decoding.
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        data_pieces (list of bytes): The list of encrypted data pieces to decrypt and reassemble.
 | 
			
		||||
        key (bytes): The encryption key to use for decrypting the data pieces.
 | 
			
		||||
        keyfile (str, optional): Path to a file containing the encryption key. If specified,
 | 
			
		||||
            the key will be read from this file instead of the `key` argument.
 | 
			
		||||
        password (str, optional): Password to use for decrypting the encryption key. If
 | 
			
		||||
            specified, the password will be used to derive the key from the keyfile.
 | 
			
		||||
    Returns:
 | 
			
		||||
        bytes: The original data obtained by reassembling the decrypted data pieces using
 | 
			
		||||
            Reed-Solomon decoding.
 | 
			
		||||
    Raises:
 | 
			
		||||
        ValueError: If both `key` and `keyfile` arguments are None, or if both are specified.
 | 
			
		||||
        IOError: If the keyfile cannot be read.
 | 
			
		||||
        ValueError: If the password is incorrect or the keyfile does not contain a valid key.
 | 
			
		||||
    """
 | 
			
		||||
    # Determine the encryption key
 | 
			
		||||
    if keyfile is not None and key is None:
 | 
			
		||||
        with open(keyfile, "rb") as f:
 | 
			
		||||
            key = f.read()
 | 
			
		||||
            if password is not None:
 | 
			
		||||
                key = scrypt(
 | 
			
		||||
                    password.encode(), KDF_SALT, KDF_KEY_LEN, N=KDF_N, r=KDF_r, p=KDF_p
 | 
			
		||||
                )
 | 
			
		||||
                if key != fernet.decrypt(key):
 | 
			
		||||
                    raise ValueError("Incorrect password or invalid key file")
 | 
			
		||||
    elif key is not None and keyfile is None:
 | 
			
		||||
        pass
 | 
			
		||||
    else:
 | 
			
		||||
        raise ValueError("Must specify either key or keyfile, but not both")
 | 
			
		||||
 | 
			
		||||
    # Decrypt each data piece and reassemble the original data
 | 
			
		||||
    piece_size = len(data_pieces[0])
 | 
			
		||||
    decoded_pieces = reedsolo.RSCodec(len(data_pieces)).decode(data_pieces)
 | 
			
		||||
    cipher = AES.new(key, AES.MODE_CBC, iv=decoded_pieces[0][:16])
 | 
			
		||||
    decrypted_data = b""
 | 
			
		||||
    for piece in decoded_pieces:
 | 
			
		||||
        decrypted_data += unpad(cipher.decrypt(piece), AES.block_size)
 | 
			
		||||
    return decrypted_data
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__":
 | 
			
		||||
    # Read encryption key from file
 | 
			
		||||
    key = read_key_from_file("./my_key.key")
 | 
			
		||||
 | 
			
		||||
    # Read data from file
 | 
			
		||||
    with open("./cat.png", "rb") as f:
 | 
			
		||||
        data = f.read()
 | 
			
		||||
 | 
			
		||||
    # Encrypt data and get nonce and encrypted pieces
 | 
			
		||||
    nonce, encrypted_pieces = encrypt_data(data, 6, keyfile="./my_key.key")
 | 
			
		||||
 | 
			
		||||
    # Decrypt data pieces
 | 
			
		||||
    decrypted_data = decrypt_data(
 | 
			
		||||
        [nonce] + encrypted_pieces, key, keyfile="./my_key.key"
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    # Write decrypted data to file
 | 
			
		||||
    with open("restored_cat.png", "wb") as f:
 | 
			
		||||
        f.write(decrypted_data)
 | 
			
		||||
							
								
								
									
										38
									
								
								pastedb/solomon/solomon-reassemble.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								pastedb/solomon/solomon-reassemble.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
import os
 | 
			
		||||
import argparse
 | 
			
		||||
from typing import List
 | 
			
		||||
from reedsolo import RSCodec
 | 
			
		||||
 | 
			
		||||
def parse_arguments():
 | 
			
		||||
    parser = argparse.ArgumentParser(description='Reassemble file from multiple Reed-Solomon encoded pieces.')
 | 
			
		||||
    parser.add_argument('input_files', type=str, nargs='+', help='List of files containing the encoded pieces, in order.')
 | 
			
		||||
    return parser.parse_args()
 | 
			
		||||
 | 
			
		||||
def reassemble_file(input_files: List[str]):
 | 
			
		||||
    # Load the encoded pieces into memory
 | 
			
		||||
    encoded_pieces = []
 | 
			
		||||
    for input_file in input_files[:-1]:
 | 
			
		||||
        with open(input_file, 'rb') as f:
 | 
			
		||||
            encoded_piece_data = f.read()
 | 
			
		||||
            encoded_piece = bytearray(encoded_piece_data)
 | 
			
		||||
            print(f"Read {len(encoded_piece)} bytes from {input_file}")  # Print the size of the bytearray
 | 
			
		||||
            encoded_pieces.append(encoded_piece)
 | 
			
		||||
 | 
			
		||||
    # Decode the pieces using Reed-Solomon coding
 | 
			
		||||
    n = len(encoded_pieces)
 | 
			
		||||
    codec = RSCodec(n)
 | 
			
		||||
    decoded_pieces = codec.decode(encoded_pieces)
 | 
			
		||||
 | 
			
		||||
    # Concatenate the decoded pieces into the original file data
 | 
			
		||||
    file_data = b''.join(decoded_pieces)
 | 
			
		||||
 | 
			
		||||
    # Write the original file data to disk
 | 
			
		||||
    output_file_path = input_files[-1]
 | 
			
		||||
    with open(output_file_path, 'wb') as f:
 | 
			
		||||
        f.write(file_data)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    args = parse_arguments()
 | 
			
		||||
    reassemble_file(args.input_files)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										63
									
								
								pastedb/solomon/solomon-test.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										63
									
								
								pastedb/solomon/solomon-test.py
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,63 @@
 | 
			
		||||
import os
 | 
			
		||||
import argparse
 | 
			
		||||
from math import ceil
 | 
			
		||||
from pydantic import BaseModel
 | 
			
		||||
from typing import List
 | 
			
		||||
from reedsolo import RSCodec
 | 
			
		||||
 | 
			
		||||
class Args(BaseModel):
 | 
			
		||||
    file_path: str
 | 
			
		||||
    n: int
 | 
			
		||||
 | 
			
		||||
def parse_arguments():
 | 
			
		||||
    parser = argparse.ArgumentParser(description='Split file into multiple pieces using Reed-Solomon coding.')
 | 
			
		||||
    parser.add_argument('file_path', type=str, help='Path to the input file.')
 | 
			
		||||
    parser.add_argument('n', type=int, help='Number of pieces to split the file into.')
 | 
			
		||||
    return Args(**vars(parser.parse_args()))
 | 
			
		||||
 | 
			
		||||
def split_file_into_pieces(file_path: str, n: int):
 | 
			
		||||
    # Load the file into memory
 | 
			
		||||
    with open(file_path, 'rb') as f:
 | 
			
		||||
        file_data = f.read()
 | 
			
		||||
 | 
			
		||||
    # Calculate the size of each piece
 | 
			
		||||
    piece_size = ceil(len(file_data) / n)
 | 
			
		||||
 | 
			
		||||
    # Create the folders for the pieces
 | 
			
		||||
    folder_names = [f'piece_{i+1}' for i in range(n)]
 | 
			
		||||
    for folder_name in folder_names:
 | 
			
		||||
        os.makedirs(folder_name, exist_ok=True)
 | 
			
		||||
 | 
			
		||||
    # Encode each piece using Reed-Solomon coding and write it to the corresponding folder
 | 
			
		||||
    codec = RSCodec(n)
 | 
			
		||||
    for i, folder_name in enumerate(folder_names):
 | 
			
		||||
        piece_data = file_data[i*piece_size:(i+1)*piece_size]
 | 
			
		||||
        encoded_data = codec.encode(piece_data)
 | 
			
		||||
        with open(os.path.join(folder_name, f'{i+1}.dat'), 'wb') as f:
 | 
			
		||||
            f.write(encoded_data)
 | 
			
		||||
 | 
			
		||||
def reassemble_file(folder_names: List[str], output_file_path: str):
 | 
			
		||||
    # Load the encoded pieces into memory
 | 
			
		||||
    encoded_pieces = []
 | 
			
		||||
    for i, folder_name in enumerate(folder_names):
 | 
			
		||||
        with open(os.path.join(folder_name, f'{i+1}.dat'), 'rb') as f:
 | 
			
		||||
            encoded_piece_data = f.read()
 | 
			
		||||
            encoded_pieces.append(encoded_piece_data)
 | 
			
		||||
 | 
			
		||||
    # Decode the pieces using Reed-Solomon coding
 | 
			
		||||
    codec = RSCodec(len(encoded_pieces))
 | 
			
		||||
    decoded_pieces = codec.decode(encoded_pieces)
 | 
			
		||||
 | 
			
		||||
    # Concatenate the decoded pieces into the original file data
 | 
			
		||||
    file_data = b''.join(decoded_pieces)
 | 
			
		||||
 | 
			
		||||
    # Write the original file data to disk
 | 
			
		||||
    with open(output_file_path, 'wb') as f:
 | 
			
		||||
        f.write(file_data)
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    args = parse_arguments()
 | 
			
		||||
    split_file_into_pieces(args.file_path, args.n)
 | 
			
		||||
    folder_names = [f'piece_{i+1}' for i in range(args.n)]
 | 
			
		||||
    reassemble_file(folder_names, 'reconstructed_file.png')
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user