summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxj9 <xj9@sunshinegardens.org>2020-06-04 22:28:11 -0600
committerxj9 <xj9@sunshinegardens.org>2020-06-04 22:28:11 -0600
commitb0b95f613d28d34cc0f96a706c0e5af16347dd03 (patch)
tree229c584c7386424abcd50a84b67da70785d67fd9
parent2987c642d77ef42de6135f5b1a4141a2995ae9ef (diff)
rlog - partial validation!
-rwxr-xr-xrlog/rlog77
1 files changed, 61 insertions, 16 deletions
diff --git a/rlog/rlog b/rlog/rlog
index bffdac0..ed05324 100755
--- a/rlog/rlog
+++ b/rlog/rlog
@@ -21,12 +21,15 @@ except ImportError:
empty_mask = bytes(32) # 256 bit / 8
class ReplicatedLog:
- def __init__(self, log_path, signing_key=None):
+ def __init__(self, log_path, signing_key=None, validate=False):
self.log_path = log_path
+ self.valid = False
if signing_key is None:
self.signing_key = nacl.signing.SigningKey.generate()
else:
self.signing_key = signing_key
+ if validate:
+ self.validate_log()
def int_to_base58(self, value):
int_bytes = '{0}'.format(value).encode()
@@ -35,39 +38,79 @@ class ReplicatedLog:
def bytes_to_int(self, value):
return int(value.decode())
- def _decode(self, message):
+ def _to_seq(self, log):
+ seq = 0
+ for line in log:
+ row = line.strip().split('\t')
+ key = row[0]
+ sig = row[1]
+ record = '\t'.join(row[2:])
+ yield (seq, key, sig, record)
+ seq += 1
+
+ def validate(self):
"""
+ validate the log
+
+ - [x] key = sha256(sig + record)
+ - [x] sig = sign(record)
+ - [ ] prev_key
+ - [ ] buffer is self-terminating
+ """
+ try:
+ with open(self.log_path) as log:
+ valid = False
+ #prev_key = None
+ for (seq, key, sig, record) in self._to_seq(log):
+ sig_record = '\t'.join((sig, record))
+ expected_key = b58encode(
+ sha256(sig_record.encode()).digest()
+ )
+ if key == expected_key.decode():
+ valid = True
+ print(seq, key, valid)
+ expected_sig = b58encode(
+ self.signing_key.sign(record.encode()).signature
+ )
+ if sig == expected_sig.decode():
+ valid = True
+ print(seq, sig, valid)
+ if not valid:
+ raise Exception('FUCK YOU')
+ if valid:
+ self.valid = True
+ return valid
+ except FileNotFoundError:
+ pass
+
+ def _decode(self, message, validate=False):
+ """
+ assuming we have a valid log, just read it
+
fields 2 and 3 can be fully parsed here
optional validation?
"""
+ result = []
index = 0
for cell in message.strip().split('\t'):
value = b58decode(cell)
if index in (2, 3):
- yield self.bytes_to_int(value)
+ result.append(self.bytes_to_int(value))
else:
- yield value
+ result.append(value)
index += 1
-
- def decode(self, message):
- """
- assuming we have a valid log, just read it
- """
- result = (value for value in self._decode(message))
return tuple(result)
- def _parse_log(self):
+ def parse_log(self):
+ log = []
try:
with open(self.log_path) as rlog:
for message in rlog:
- yield self.decode(message)
+ log.append(self._decode(message))
except FileNotFoundError:
pass
-
- def parse_log(self):
- log = tuple((message for message in self._parse_log()))
- return log, (len(log) - 1)
+ return tuple(log), (len(log) - 1)
def get_prev_key(self):
"""
@@ -158,4 +201,6 @@ if __name__ == '__main__':
log.append_message('ACAB'.encode())
log.append_message('Antifaschistische Aktion'.encode())
print(open(test_log).read())
+ log.validate()
+ print('Log=Valid' if log.valid else 'Log!Valid')
os.remove(test_log)