Reed-solomon testing and btc wallet generator.
This commit is contained in:
parent
582844bacf
commit
ec4104b2d1
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):
|
def upload_and_store(data: Dict):
|
||||||
# set encryption key if necessary
|
# 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 = {}
|
traces = {}
|
||||||
for service in [pastie, dpaste, rentry, defau, sprunge, opendev]:
|
for service in [pastie, dpaste, rentry, defau, sprunge, opendev]:
|
||||||
@ -13,11 +14,13 @@ def upload_and_store(data: Dict):
|
|||||||
if result:
|
if result:
|
||||||
traces[result['name']] = result['key']
|
traces[result['name']] = result['key']
|
||||||
add_data(service.get_service_tag(), result['name'], result['md5sum'])
|
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
|
return traces
|
||||||
|
|
||||||
my_data = {"name": "Sashenka", "age": 26, "country": "Anguilla"}
|
my_data = {"name": "Sashenka", "age": 26, "country": "Anguilla"}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
upload_trace = upload_and_store(my_data)
|
upload_trace = upload_and_store(my_data)
|
||||||
|
|
||||||
print('trace: ', upload_trace)
|
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')
|
||||||
|
|
Loading…
Reference in New Issue
Block a user