def transaction(e, d): """ """ k = ecc.ecdsa() src, dst, dat, lat, mnt, ref = e[:8], e[8:16], e[16:20], e[20:28], e[28:32], e[32:40] msg, sig, now = e[:-96], e[-96:], ecc.datint() if src not in d.keys() or dst not in d.keys() or src == dst: return b'Error database' dls, dld = d[src][4:], d[dst][4:] zx, zd = ecc.b2h(src), ecc.b2h(dst) if zx not in d.keys(): return b'Error public key' k.pt = k.uncompress(ecc.h2b(zx + d[zx])) if not k.verify(sig, msg): return b'Error signature' val, bals, bald = ecc.b2i(mnt), balance(src, d), balance(dst, d) if val <= 0 or bals - val < -MAXBAL or bald + val > MAXBAL: return b'Error value' os, od = ecc.b2i(d[src][:4]), ecc.b2i(d[dst][:4]) ns, nd = os + 1, od + 1 nhs = ecc.z10 if os == 0 else d[src + ecc.i2b(os, 4)][-10:] nhd = ecc.z10 if od == 0 else d[dst + ecc.i2b(od, 4)][-10:] lst_tot, lst_wlt = ecc.b2i(d[ecc.v1][:8]), ecc.b2i(d[ecc.v1][8:]) if ecc.b2i(dls) <= now or ecc.b2i(dld) <= now or ecc.b2i(dat) > now: return b'Error deadline' if os > 0: dx = src + ecc.i2b(os, 4) if len(d[dx]) == NS: dx = d[dx][:12] if ecc.b2i(d[dx][8:12]) >= ecc.b2i(dat): return b'Wait a minute !' nws, nwd = ecc.s2b(bals - val, 4), ecc.s2b(bald + val, 4) sm, dm = dst + ecc.i2b(nd, 4) + nws, src + dat + lat + mnt + ref + sig + nwd # BEGIN WRITE SECTION d[src] = ecc.i2b(ns, 4) + dls d[src + ecc.i2b(ns, 4)] = sm + hashlib.sha1(src + sm + nhs).digest()[:10] d[dst] = ecc.i2b(nd, 4) + dld d[dst + ecc.i2b(nd, 4)] = dm + hashlib.sha1(dst + dm + nhd).digest()[:10] d[ecc.v1] = ecc.i2b(lst_tot + 1, 8) + ecc.i2b(lst_wlt + val, 8) # END WRITE SECTION return b'TRANSACTION from ' + zx + b' to ' + zd
def log(self): " Just for debugging " print('USER', self.name, 'Raw-balance:', self.bal, 'Said:', len(self.ids), 'ids') for i, j in enumerate(self.ids): print('%02d' % (i + 1), ecc.b2h(j[0][1:]), j[1:]) print('USER', self.name, 'Heard:', len(self.cts), 'ids') for x in self.cts: print(' ', ecc.b2h(x[1:]), self.cts[x])
def register(e, d): "" zid, dl = ecc.b2h(e[:8]), ecc.add1year(ecc.datencode()) if len(d.keys()) == 2 else ecc.z4 for i in range(1, 16): if sum([1 for x in d.keys() if len(x) == 16]) < (16**i)//2: break for x in d.keys(): if len(x) == 16 and x[:i] == zid[:i]: return ('COLISION %s [%d] -> re-run generation !' % (zid, i)).encode('UTF-8') if zid in d: return b'COLISION!' # START WRITING d[e[:8]] = ecc.z4 + dl d[zid] = ecc.b2h(e[8:]) # STOP WRITING return zid + b' registered'
def candidate(data, d): ky, mel , o = data[:48], data[48:], b'' with dbm.open('mel', 'c') as m: if mel not in m: o = register(ky, d) if o[:8] != b'COLISION': m[mel] = ecc.b2h(ky[:8]) return o
def phone(db, ip, unik=False): """ IO CLIENT: Simulate smart-phone with strong authentication Commands: l -> list index of all registered bodies r email -> register a new body with a new email <num> -> select <num> as current body v -> verify all the database s -> return server public id o -> return proof of balance at current time, to give to offline objects c <num> -> request certificate to <num> or generate certificate for <num> p <num> <val> -> pay <num> body <val> amount of leaf h -> display history for current body m -> list all client ids (usually one if flag unik is True) b -> begin counting resource by object e -> end counting resource by object """ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) print ('IO Client (Phone)\nType ? for help') my = b'' while True: if my == b'': my = get_my('1') cmd, req, bmy = input('%s >' % my.decode('UTF-8')), b'', ecc.h2b(my) if leaf.reg(re.match('(r|reg|register)\s*(\w{2,20}@\w{2,20}\.\w{2,3})\s*$', cmd)): # 48 with dbm.open(db, 'c') as d: req = genkey(leaf.reg.v.group(2).encode('UTF-8'), unik, d) elif re.match('(v|verif|verification)\s*$', cmd): req = b'v' elif re.match('(l|ls|list)\s*$', cmd): req = b'l' elif re.match('(s|server)\s*$', cmd): req = b's' elif re.match('(h|hist|history)\s*$', cmd): req = my elif re.match('(o|proof)\s*$', cmd): req = bmy elif re.match('(\?|help)\s*$', cmd): req = b''; print (__doc__, phone.__doc__) elif re.match('(b|begin|start)\s*$', cmd): req = b''; start_access() elif re.match('(e|end|stop)\s*$', cmd): req = b''; stop_access() elif leaf.reg(re.match('(my|)\s*(\d{1,2})\s*$', cmd)): my = get_my(leaf.reg.v.group(2)) elif leaf.reg(re.match('(p|pay)\s*(\d{1,2})\s+(\d{1,3})\s*$', cmd)): # 136 with dbm.open(db) as d: pld = ecc.i2b(int(leaf.reg.v.group(3)), 4) req = gene(bmy, ecc.h2b(get_my(leaf.reg.v.group(2))), pld, d) elif leaf.reg(re.match('(c|crt|cert)\s*(\d{1,2})\s*$', cmd)): # len:142 with dbm.open(db) as d: req = gene(bmy, ecc.h2b(get_my(leaf.reg.v.group(2))), ecc.z10, d) elif re.match('(m|my)\s*$', cmd): with dbm.open(db) as d: for x in d.keys(): print (ecc.b2h(x).decode('UTF-8')) req = b'' elif re.match('(q|quit)\s*$', cmd): s.close() break if req: s.sendto(req, (ip, PORT1)) data, addr = s.recvfrom(2048) if data: print (data.decode('UTF-8')) if req == b'l': with open('lpub', 'w') as f: f.write(data.decode('UTF-8')) elif req == bmy: with open('proof', 'w') as f: f.write(data.decode('UTF-8'))
def proof(x, d): "" if b'SERVER' in d.keys(): k = ecc.ecdsa() pk, sk = d[b'SERVER'][:48], d[b'SERVER'][48:] k.pt, k.privkey = k.uncompress(pk), ecc.b2i(sk) dat = ecc.datdecode(ecc.datencode()).encode('UTF-8') msg = b'%s %d %s' % (ecc.b2h(x), balance(x, d), dat) return ecc.z85encode(k.sign(msg)) + msg if not verif(d) else b'error' return b''
def certificate(e, d): """ A(green) if first B->A if A(green)B(red) then B(orange) A->B if A(green)B(orange) then B(green) """ k = ecc.ecdsa() src, dst, dat, lat, pld, ref = e[:8], e[8:16], e[16:20], e[20:28], e[28:38], e[38:46] msg, sig, now = e[:-96], e[-96:], ecc.datint() if ecc.b2i(dat) > now: return b'future date' if src not in d.keys() or dst not in d.keys() or src == dst: return b'Error database' zx = ecc.b2h(src) if zx not in d.keys(): return b'Error public key' k.pt = k.uncompress(ecc.h2b(zx + d[zx])) if not k.verify(sig, msg): return b'Error signature' green, orang, red = ecc.add1year(ecc.datencode()), ecc.datencode(), ecc.z4 os, od = ecc.b2i(d[src][:4]), ecc.b2i(d[dst][:4]) ns, nd = os + 1, od + 1 nhs = ecc.z10 if os == 0 else d[src + ecc.i2b(os, 4)][-10:] if os > 0: dx = src + ecc.i2b(os, 4) if len(d[dx]) == NS: dx = d[dx][:12] if ecc.b2i(d[dx][8:12]) >= ecc.b2i(dat): return b'Wait a minute !' nws = ecc.s2b(balance(src, d), 4) sm = dst + dat + lat + pld + ref + sig + nws # START WRITING if ecc.b2i(d[dst][4:]) > ecc.datint() and d[src][4:] == red: d[src] = ecc.i2b(ns, 4) + orang d[src + ecc.i2b(ns, 4)] = sm + hashlib.sha1(src + sm + nhs).digest()[:10] d[ecc.v1] = ecc.i2b(ecc.b2i(d[ecc.v1][:8]) + 1, 8) + d[ecc.v1][8:] return b'REQUEST by ' + zx if ecc.b2i(d[src][4:]) > ecc.datint() and d[dst][4:] != red: d[dst] = d[dst][:4] + green d[src] = ecc.i2b(ns, 4) + d[src][4:] d[src + ecc.i2b(ns, 4)] = sm + hashlib.sha1(src + sm + nhs).digest()[:10] d[ecc.v1] = ecc.i2b(ecc.b2i(d[ecc.v1][:8]) + 1, 8) + d[ecc.v1][8:16] return b'CERTIFICATION by ' + zx # STOP WRITING else: return b'Error request'
def history(e, d): "" x = ecc.h2b(e) n = ecc.b2i(d[x][:4]) o = [e + b' nb: %04d balance: %6d' % (n, balance(x, d))] for i in range(n): dx = x + ecc.i2b(i+1, 4) h, zx, y = ecc.b2i(d[dx][-10:]), ecc.b2h(d[dx][:8]), d[dx] bal = ecc.b2s(y[-14:-10], 4) if len(y) == NS: dx = d[dx][:12] if len(y) == NC: val, sg, dat = 0, b' ', ecc.datdecode(d[dx][8:12]) elif len(y) == ND: val = ecc.b2i(d[dx][20:24]) dat = ecc.datdecode(d[dx][8:12]) sg = b'+' elif len(y) == NS: val = ecc.b2i(d[dx][20:24]) dat = ecc.datdecode(d[dx][8:12]) sg = b'-' o.append(b'%03d %s%3d %8d H:%020X %s %s' % (i+1, sg, val, bal, h, zx, dat.encode('UTF-8'))) o.append(b'Balance: %6d' % balance(x, d) ) return b'\n'.join(o)
def verif(d): """ check certification ! """ print ('run check!') k = ecc.ecdsa() if len(d.keys()) > 0 and ecc.v1 not in d: return 0x01 # head does not exists wc, wr, tc, tr, al = 0, 0, 0, 0, 0 lo = [] for i in [x for x in d.keys() if len(x) == 16]: x = ecc.h2b(i) if ecc.b2i(d[x][4:]) > ecc.datint(): lo.append(x) #print (lo) #find the root for x in d.keys(): # Length lk, lv = len(x), len(d[x]) if lk == 1: wr, tr = ecc.b2i(d[x][8:16]), ecc.b2i(d[x][:8]) if lk == 1 and lv != 16: return 0x02 # bad length head if lk == 5 and lv != 96: return 0x03 # bad length server id if lk == 8 and lv != 8: return 0x04 # bad length id head if lk == 12 and lv not in (NS, ND, NC): return 0x05 # bad length operation if lk == 16 and lv != 80: return 0x06 # bad length pub key # Public keys if lk == 12: if ecc.b2h(x[:8]) not in d: return 0x07 # src id unknown if ecc.b2h(d[x][:8]) not in d: return 0x08 # dst id unknown if lk == 8: # Money supply al += balance(x, d) # Dates dat = ecc.z8 for i in range(ecc.b2i(d[x][:4])): dx = x + ecc.i2b(i+1, 4) if len(d[dx]) in (ND, NC): if d[dx][8:12] <= dat: return 0x09 # bad date increase dat = d[dx][8:12] if len(d[dx]) == ND: if dat > d[x][4:]: return 0x0A # invalid date/dead line # Signatures for i in range(ecc.b2i(d[x][:4])): dx = x + ecc.i2b(i+1, 4) if len(d[dx]) == NC: src, dst = x, d[dx][:8] if len(d[dx]) == ND: src, dst = d[dx][:8], dx[:8] if len(d[dx]) in (NC, ND): zx = ecc.b2h(src) if zx not in d.keys(): return 0x0B # Error public key msg, sig = src + dst + d[dx][8:-110], d[dx][-110:-14] k = ecc.ecdsa() k.pt = k.uncompress(ecc.h2b(zx + d[zx])) if not k.verify(sig, msg): return 0x0C # bad signature # Hash h = ecc.z10 for i in range(ecc.b2i(d[x][:4])): dx = x + ecc.i2b(i+1, 4) h = hashlib.sha1(x + d[dx][:-10] + h).digest()[:10] if h != d[dx][-10:]: return 0x0D # bad hash # Wealth for i in range(ecc.b2i(d[x][:4])): dx = x + ecc.i2b(i+1, 4) if len(d[dx]) == ND: wc += ecc.b2i(d[dx][20:24]) # Operations counter for i in range(ecc.b2i(d[x][:4])): dx = x + ecc.i2b(i+1, 4) if len(d[dx]) in (ND, NC): tc += 1 # Balances b = 0 for i in range(ecc.b2i(d[x][:4])): dx = x + ecc.i2b(i+1, 4) if dx not in d: return 0x0E # missing transaction if len(d[dx]) == ND: b += ecc.b2i(d[x + ecc.i2b(i+1, 4)][20:24]) elif len(d[dx]) == NS: b -= ecc.b2i(d[d[dx][:12]][20:24]) if b != ecc.b2s(d[dx][-14:-10], 4): return 0x0F # bad balance if b < -MAXBAL or b > MAXBAL: return 0x10 # Out of bounds if wc != wr: return 0x11 # bad wealth if tc != tr: return 0x12 # bad counter if al != 0: return 0x13 # bad money supply return 0 # Everythink ok !