Использование HMAC с SHA-256
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
KEY="sicret_key"
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
import json
|
||||||
|
import os
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
from nonce_finder import NonceFinder
|
||||||
|
|
||||||
|
|
||||||
|
class Block:
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
name,
|
||||||
|
amount,
|
||||||
|
to_whom_name,
|
||||||
|
nonce=0,
|
||||||
|
prev_hash='00000000000000000000000000000000'
|
||||||
|
):
|
||||||
|
self.name = name
|
||||||
|
self.amount = amount
|
||||||
|
self.to_whom_name = to_whom_name
|
||||||
|
self.nonce = nonce
|
||||||
|
self.prev_hash = prev_hash
|
||||||
|
self.standard_path = 'blockchain_blocks/'
|
||||||
|
dotenv_path = os.path.join(os.path.dirname(__file__), '.env')
|
||||||
|
if os.path.exists(dotenv_path):
|
||||||
|
load_dotenv(dotenv_path)
|
||||||
|
self.key = os.environ.get('KEY')
|
||||||
|
|
||||||
|
def get_last_block(self):
|
||||||
|
""" Получение номера последнего блока """
|
||||||
|
try:
|
||||||
|
files = [int(f.split('.')[0])
|
||||||
|
for f in os.listdir(self.standard_path) if f.endswith('.txt')]
|
||||||
|
return max(files, default=0)
|
||||||
|
except ValueError:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def data_creator(self):
|
||||||
|
""" Создание данных блока """
|
||||||
|
return [
|
||||||
|
{'nonce': self.nonce},
|
||||||
|
{'from': self.name, 'amount': self.amount, 'to_whom': self.to_whom_name},
|
||||||
|
{'preview_hash': self.prev_hash}
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_last_block_hash(self, filename):
|
||||||
|
""" Получение хэша последнего блока """
|
||||||
|
with open(
|
||||||
|
os.path.join(self.standard_path, str(int(filename) - 1) + '.txt'),
|
||||||
|
'r'
|
||||||
|
) as file:
|
||||||
|
return json.load(file)[1]
|
||||||
|
|
||||||
|
def block_creator(self):
|
||||||
|
""" Создание нового блока """
|
||||||
|
last_file = self.get_last_block()
|
||||||
|
filename = str(last_file + 1)
|
||||||
|
data = self.data_creator()
|
||||||
|
if last_file != 0:
|
||||||
|
data[2]['preview_hash'] = self.get_last_block_hash(filename)
|
||||||
|
block_hash = NonceFinder(data, 4, self.key).create_pow()[1]
|
||||||
|
result_dump_data = [data, block_hash]
|
||||||
|
with open(os.path.join(self.standard_path, filename + '.txt'), 'w') as file:
|
||||||
|
json.dump(result_dump_data, file, indent=4, ensure_ascii=False)
|
||||||
|
if last_file == 0:
|
||||||
|
print('[+] Создан первый блок')
|
||||||
|
else:
|
||||||
|
print(f'[+] Блок {filename} создан')
|
||||||
|
|
||||||
|
def blockchain_checker(self):
|
||||||
|
""" Проверка целостности блокчейна """
|
||||||
|
files = sorted([f for f in os.listdir(self.standard_path) if f.endswith('.txt')],
|
||||||
|
key=lambda x: int(x.split('.')[0]))
|
||||||
|
for file in files[1:]:
|
||||||
|
with open(os.path.join(self.standard_path, file), 'r') as current_file:
|
||||||
|
current_block = json.load(current_file)
|
||||||
|
prev_hash = current_block[0][2]['preview_hash']
|
||||||
|
prev_file = str(int(file.split('.')[0]) - 1) + ".txt"
|
||||||
|
with open(os.path.join(self.standard_path, prev_file), 'r') as _file:
|
||||||
|
prev_block_data = json.load(_file)[0]
|
||||||
|
real_prev_block_hash = NonceFinder(
|
||||||
|
prev_block_data,
|
||||||
|
4,
|
||||||
|
self.key
|
||||||
|
).create_pow()[1]
|
||||||
|
if prev_hash == real_prev_block_hash:
|
||||||
|
print(f'[+] Блок {prev_file} верен')
|
||||||
|
else:
|
||||||
|
print(f'[-] В блоке {prev_file} допущена ошибка!')
|
||||||
|
if len(files) <= 1:
|
||||||
|
print('[+] Для начала проверки цепочки блоков, создайте больше блоков!')
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
[
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"nonce": 19
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": "from",
|
||||||
|
"amount": 100,
|
||||||
|
"to_whom": "to_whom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"preview_hash": "00000000000000000000000000000000"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"0c5955b05fb75c1708d05dd4e2e2300e6758ffcdf4fe0a25d7293c102daf9781"
|
||||||
|
]
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
[
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"nonce": 25
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": "from",
|
||||||
|
"amount": 100,
|
||||||
|
"to_whom": "to_whom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"preview_hash": "0cbe01edb3f7f3996303e7cfe3fbd65798a62395c6fcf8b81a367029829b6be7"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"025bd21c54fd5a884de2be718f4e049bbc72cd5db2b5e1dcce7a356a8f53975a"
|
||||||
|
]
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
[
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"nonce": 37
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": "from",
|
||||||
|
"amount": 100,
|
||||||
|
"to_whom": "to_whom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"preview_hash": "025bd21c54fd5a884de2be718f4e049bbc72cd5db2b5e1dcce7a356a8f53975a"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"07aab394731dc039195ad5c6c5a7bb7af66951afbf9ada85524fdcf19ab07b98"
|
||||||
|
]
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
[
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"nonce": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": "from",
|
||||||
|
"amount": 100,
|
||||||
|
"to_whom": "to_whom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"preview_hash": "07aab394731dc039195ad5c6c5a7bb7af66951afbf9ada85524fdcf19ab07b98"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"0d263ee60a28d4e6230a9980b10761ec1039a39b497e508530143a702c3efe47"
|
||||||
|
]
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
[
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"nonce": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": "from",
|
||||||
|
"amount": 100,
|
||||||
|
"to_whom": "to_whom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"preview_hash": "0d263ee60a28d4e6230a9980b10761ec1039a39b497e508530143a702c3efe47"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"03c9615b639aa5350dfd3aa8ac9b405ee6cd3d556cf4e55a3a912f0ca7c3a45b"
|
||||||
|
]
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
[
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"nonce": 17
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": "from",
|
||||||
|
"amount": 100,
|
||||||
|
"to_whom": "to_whom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"preview_hash": "0c5955b05fb75c1708d05dd4e2e2300e6758ffcdf4fe0a25d7293c102daf9781"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"08cf9f3a545684c6e9509b5b85717da1007710c363303d8077ac3dc4770af892"
|
||||||
|
]
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
[
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"nonce": 12
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": "from",
|
||||||
|
"amount": 100,
|
||||||
|
"to_whom": "to_whom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"preview_hash": "08cf9f3a545684c6e9509b5b85717da1007710c363303d8077ac3dc4770af892"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"0666bdd3addb25eb0c3a7a87df7ffdceaf4e0cd12310bc279d61c47fe9c5b6cd"
|
||||||
|
]
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
[
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"nonce": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": "from",
|
||||||
|
"amount": 100,
|
||||||
|
"to_whom": "to_whom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"preview_hash": "0666bdd3addb25eb0c3a7a87df7ffdceaf4e0cd12310bc279d61c47fe9c5b6cd"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"02e234bf063fba31a1824bb318bd9b99de3c2c8581796f764044eb244f569069"
|
||||||
|
]
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
[
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"nonce": 21
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": "from",
|
||||||
|
"amount": 100,
|
||||||
|
"to_whom": "to_whom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"preview_hash": "02e234bf063fba31a1824bb318bd9b99de3c2c8581796f764044eb244f569069"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"0501207886e3008ab0fb5ce4def8805feb8feae9260be2ea317d2a6c452ba3e5"
|
||||||
|
]
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
[
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"nonce": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": "from",
|
||||||
|
"amount": 100,
|
||||||
|
"to_whom": "to_whom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"preview_hash": "0501207886e3008ab0fb5ce4def8805feb8feae9260be2ea317d2a6c452ba3e5"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"024b09c7b1535ebcfa0358043ebd41886066260bc5c7b6bd040a3b7591e27ff9"
|
||||||
|
]
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
[
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"nonce": 38
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": "from",
|
||||||
|
"amount": 100,
|
||||||
|
"to_whom": "to_whom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"preview_hash": "024b09c7b1535ebcfa0358043ebd41886066260bc5c7b6bd040a3b7591e27ff9"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"08785202610c8ff63d151b0df7a53f2b22fbc5cfb149cfeb0ba79b63710df9e6"
|
||||||
|
]
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
[
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"nonce": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": "from",
|
||||||
|
"amount": 100,
|
||||||
|
"to_whom": "to_whom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"preview_hash": "08785202610c8ff63d151b0df7a53f2b22fbc5cfb149cfeb0ba79b63710df9e6"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"06c09c9cf00307b85af725eb39a91e6bc88f0aa9650584a4050c2416efecbd1a"
|
||||||
|
]
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
[
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"nonce": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from": "from",
|
||||||
|
"amount": 100,
|
||||||
|
"to_whom": "to_whom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"preview_hash": "06c09c9cf00307b85af725eb39a91e6bc88f0aa9650584a4050c2416efecbd1a"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"0cbe01edb3f7f3996303e7cfe3fbd65798a62395c6fcf8b81a367029829b6be7"
|
||||||
|
]
|
||||||
@@ -1,16 +1,15 @@
|
|||||||
# This is a sample Python script.
|
import sys
|
||||||
|
from Block import Block
|
||||||
# Press Shift+F10 to execute it or replace it with your code.
|
|
||||||
# Press Double Shift to search everywhere for classes, files, tool windows, actions, and settings.
|
|
||||||
|
|
||||||
|
|
||||||
def print_hi(name):
|
def main():
|
||||||
# Use a breakpoint in the code line below to debug your script.
|
if len(sys.argv) == 4:
|
||||||
print(f'Hi, {name}') # Press Ctrl+F8 to toggle the breakpoint.
|
block = Block(sys.argv[1], sys.argv[2], sys.argv[3])
|
||||||
|
else:
|
||||||
|
block = Block('from', 100, 'to_whom')
|
||||||
|
block.block_creator()
|
||||||
|
block.blockchain_checker()
|
||||||
|
|
||||||
|
|
||||||
# Press the green button in the gutter to run the script.
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
print_hi('PyCharm')
|
main()
|
||||||
|
|
||||||
# See PyCharm help at https://www.jetbrains.com/help/pycharm/
|
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
import itertools
|
||||||
|
import hashlib
|
||||||
|
import hmac
|
||||||
|
|
||||||
|
|
||||||
|
class NonceFinder:
|
||||||
|
def __init__(self, data, difficulty, key):
|
||||||
|
self.data = data
|
||||||
|
self.difficulty = difficulty
|
||||||
|
self.key = key
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def to_long(x):
|
||||||
|
return sum(ord(b) << (8 * i) for i, b in enumerate(x))
|
||||||
|
|
||||||
|
def verify_pow(self, nonce):
|
||||||
|
self.data[0]['nonce'] = nonce
|
||||||
|
# Использование HMAC с SHA-256
|
||||||
|
combined_data = str(self.data).encode()
|
||||||
|
hmac_result = hmac.new(self.key.encode(), combined_data, hashlib.sha256).hexdigest()
|
||||||
|
return self.to_long(list(hmac_result)) % (1 << self.difficulty) == 0
|
||||||
|
|
||||||
|
def create_pow(self):
|
||||||
|
for nonce in itertools.count(0):
|
||||||
|
if self.verify_pow(nonce):
|
||||||
|
combined_data = str(self.data).encode()
|
||||||
|
hmac_result = hmac.new(
|
||||||
|
self.key.encode(),
|
||||||
|
combined_data,
|
||||||
|
hashlib.sha256
|
||||||
|
).hexdigest()
|
||||||
|
return nonce, hmac_result
|
||||||
Generated
+20
@@ -0,0 +1,20 @@
|
|||||||
|
# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand.
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "python-dotenv"
|
||||||
|
version = "1.0.0"
|
||||||
|
description = "Read key-value pairs from a .env file and set them as environment variables"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "python-dotenv-1.0.0.tar.gz", hash = "sha256:a8df96034aae6d2d50a4ebe8216326c61c3eb64836776504fcca410e5937a3ba"},
|
||||||
|
{file = "python_dotenv-1.0.0-py3-none-any.whl", hash = "sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
cli = ["click (>=5.0)"]
|
||||||
|
|
||||||
|
[metadata]
|
||||||
|
lock-version = "2.0"
|
||||||
|
python-versions = "^3.11"
|
||||||
|
content-hash = "c5e9d7ef80551206531e74c9c51ba97d4b66d8df66a3398da6afb0391f703375"
|
||||||
@@ -7,6 +7,7 @@ readme = "README.md"
|
|||||||
|
|
||||||
[tool.poetry.dependencies]
|
[tool.poetry.dependencies]
|
||||||
python = "^3.11"
|
python = "^3.11"
|
||||||
|
python-dotenv = "^1.0.0"
|
||||||
|
|
||||||
|
|
||||||
[build-system]
|
[build-system]
|
||||||
|
|||||||
Reference in New Issue
Block a user