def server(db, ip): """ """ k = ecc.ecdsa() s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.bind((ip, PORT1)) print ('IO-server on %s' % ip) with dbm.open(db, 'c') as d: if len(d.keys()) == 0: k.generate() sk, pk = ecc.i2b(k.privkey, 48), k.compress(k.pt) d[b'SERVER'] = pk + sk d[ecc.v1] = ecc.z8 + ecc.z8 with open('server_pk', 'w') as f: f.write(ecc.z85encode(pk).decode('UTF-8')) print ('Server Public ID: ' + server_id(d).decode('UTF-8')) if ecc.v1 in d.keys(): print ('Wealth: %d [%d operations]' % (ecc.b2i(d[ecc.v1][8:]),ecc.b2i(d[ecc.v1][:8]) )) while True: (data, addr), o = s.recvfrom(1024), b'' with dbm.open(db, 'c') as d: if len(data) == 1: if data == b'v': o = b'Error %02X' % verif(d) elif data == b'l': o = list_humans(d) elif data == b's': o = server_id(d) elif len(data) == 8: o = proof (data, d) elif len(data) == 16: o = history (data, d) elif len(data) == 93: o = candidate (data, d) elif len(data) == 136: o = transaction(data, d) elif len(data) == 142: o = certificate(data, d) elif len(data) >= 144 and len(data) <= 256: o = invoice(data, d) else: o = b'command not found!' s.sendto(o, addr)
def regrp(s, m): x, h, g, pr, p, y, z = m[:5], m[5:7], b'_' + m[5:7], m[7:8], ecc.b2i(m[7:8]), 0, 0 with dbm.open(s.n, 'c') as b: b[x+h] = pr if h not in b: b[h] = ecc.z6 z = ecc.b2i(b[g]) if g in b else 0 b[g] = ecc.i2b(z + p, 4)
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 get(s, tt): print(len(tt)) # min 634 t, a = tt[:-SAJ], tt[-SAJ:] assert len(t) % SIZE == 0 for i in range(len(t) // SIZE): m = t[i * SIZE:(i + 1) * SIZE] c, p, e, g = m[:96], m[96:144], m[144:-96], m[-96:] if i == 0: c0, p0, e0, b, src = c, p, e, BloomFilter.loads( e[-BSIZ - 16:-16]), e[:8] else: assert src == e[10:18] and '%s' % e[:10] not in b b += '%s' % e[:10] assert s.root.k.verify(c, e[:8]) # certificate s.o.pt = s.o.uncompress(p) assert s.o.verify(g, e) # in signature m1 = src + num(getn(e0) + 1) + s.i + a[8:12] + bal( getb(e0) - ecc.b2i(a[8:12])) + a[12:16] + b.dumps() + hsh(t) assert ecc.b2i(a[12:16]) > getd(e0) ak = a[-192:-96] s.o.pt = s.o.uncompress(a[16:16 + 48]) assert s.o.verify(ak, src + num(getn(e0))) # ack signature s.o.pt = s.o.uncompress(p0) assert s.o.verify(a[-96:], m1) # final signature s.tp[c0 + p0 + m1 + a[-96:]] = True s.b += getm(m1)
def time(s, p): if s.rvs[p] == 'PUB': return 0 t = 0 with dbm.open(s.n) as b: for x in [y for y in b.keys() if len(y) == MEKL and len(b[y]) == MEVL]: if p == x[:5]: t += ecc.b2i(b[x][3:]) elif p == x[5:]: t += ecc.b2i(b[x][3:]) else: assert s.n == 'PUB' return t
def groups(s): with dbm.open(s.n) as b: g, d = {}, {} for x in [y for y in b.keys() if len(y) == 7 and len(b[y]) == 1]: gr, el, pt = ecc.b2i(x[5:]), s.rvs[x[:5]], ecc.b2i(b[x]) h = g[gr] if gr in g else {} h[el] = pt g[gr] = h for x in [y for y in b.keys() if len(y) == 3 and len(b[y]) == 4]: d[ecc.b2i(x[1:])] = ecc.b2i(b[x]) return (g, d)
def object(db, ip): "" k, t = ecc.ecdsa(), socket.socket(socket.AF_INET, socket.SOCK_DGRAM) print ('Intelligent Object (socket open)') with dbm.open(db, 'c') as d: if len(d.keys()) == 0: k.generate() sk, pk = ecc.i2b(k.privkey, 48), k.compress(k.pt) d[b'KEYS'] = pk + sk t.bind((ip, PORT2)) while True: (data, addr) = t.recvfrom(1024) with open('server_pk') as f: pk = f.read() k.pt = k.uncompress(ecc.z85decode(pk.encode('UTF-8'))) if len(data)>130: sig, msg = ecc.z85decode(data[:120]), data[120:] if k.verify(sig, msg): cod = random.randrange(10000) t.sendto(b'start counting (code:%04d)' % cod, addr) dat = time.time() else: t.sendto(b'error on signature', addr) elif len(data) == 4: with dbm.open(db, 'c') as d: print (' %d secondes' % int(time.time()-dat)) pk, sk = d[b'KEYS'][:48], d[b'KEYS'][48:] k.pt, k.privkey = k.uncompress(pk), ecc.b2i(sk) msg = b'invoice for %d secondes' % int(time.time()-dat) cmd = ecc.z85encode(k.sign(msg)) + msg t.sendto(cmd, addr) else: t.sendto(b'error', addr)
def chresp(s, cand): assert cand not in s.un if ecc.b2i(cand[8:10]) == 0: s.un[cand] = True return s.p + s.k.sign(cand) for x in [y for y in s.tp if y[144:154] == cand]: s.un[cand] = True return s.p + s.k.sign(cand) return
def manage_post(s, d): k = ecc.ecdsa() s.response('application/octet-stream') if len(d) != RLEN: return False if s.nod.me not in s.nod.tid: return False if not s.nod.check(s.nod.tid[s.nod.me], ecc.b2i(d[10:13])): return False k.pt = k.uncompress(s.nod.tid[s.nod.me] + s.nod.tpk[s.nod.tid[s.nod.me]]) if not k.verify(d[16:], d[:16]): return False return s.nod.manage(d)
def list_humans(d): "" lu, lo = [x for x in d.keys() if len(x) == 16], [] for p, i in enumerate(lu): x = ecc.h2b(i) ct = (' %6d' % balance(x, d)).encode('UTF-8') if ecc.b2i(d[x][4:]) > ecc.datint() else b'' perso = b'' # provision lo.append( ('%d\t' % (p+1)).encode('UTF-8') + i + ct + perso) return b'\n'.join(lo)
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 status(s): exposed = {} print ('Balance %d' % s.balance) if ecc.os.path.isfile('db%d/exposed'%s.p): with dbm.open('db%d/exposed'%s.p) as b: for x in b.keys(): exposed[x] = (datdecode(b[x][:4]), ecc.b2i(b[x][-1:])) with dbm.open('db%d/hear'%s.p) as b: for x in [y for y in b.keys() if y in exposed]: return 'risk level %s %d' % (exposed[x][0], exposed[x][1]) return 'ok'
def gene(bmy, dst, pld, d): "" if bmy in d.keys(): k = ecc.ecdsa() pk, sk = bmy + d[bmy][:40], d[bmy][40:] k.pt, k.privkey = k.uncompress(pk), ecc.b2i(sk) msg = pk[:8] + dst + ecc.datencode() + ecc.z8 + pld + ecc.z8 return msg + k.sign(msg) else: print ('you do not own that key') return b''
def manage(s, m, a=None): t, k = socket.socket(socket.AF_INET, socket.SOCK_DGRAM), ecc.ecdsa() k.pt, dst = k.uncompress(m[:5] + s.tpk[m[:5]]), s.rvs[m[5:10]] if s.n != 'PUB' and m[5:10] != s.tid[s.n] : return False if not k.verify(m[MLEN:RLEN], m[:MLEN]) : return False if len(m) > RLEN: s.sync(m[RLEN:]) if s.pos(m[:10]) == m[14:16]: if s.n == 'PUB' and not s.check(m[:5], ecc.b2i(m[10:13])): return False s.add(m) # add dst or PUB if s.n == 'PUB' and a: t.sendto(s.readsync(), a) if dst in s.tbl: t.sendto(m + s.readsync(), (HOST, s.tbl[dst])) else: print ('record for iphone') s.pending(m[:RLEN]) print (s.bals()) return True else: return ecc.b2i(s.pos(m[:10])) == ecc.b2i(m[14:16]) + 1
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 test(self, u): for x in u: x.pretest(self) self.tax, k, tab = sum([ecc.b2i(x[-1:]) // 5 for x in self.hse[0]]), ecc.ecdsa(), {} for x in u: x.test(self) assert operator.eq(self.hse[0].keys(), self.hse[1].keys()) # VERIF 1: no leaks assert sum([x.bal for x in u]) + self.tax == 0 # VERIF 2: sum balances null for x in self.hse[0]: for z in [y for y in self.pks if y[:8] == self.hse[0][x][0]]: k.pt = k.uncompress(z) assert k.verify(self.hse[0][x][1], x) # VERIF 3: Transaction signature ok for x in self.hse[0]: y, pr = self.hse[0][x][0], ecc.b2i(x[-1:]) tab[y] = tab[y] + pr if y in tab else pr for z in [x for x in self.hse[1] if self.hse[1][x] in tab]: tab[self.hse[1][z]] -= ecc.b2i(z[-1:]) for t in tab: assert tab[t] < MAXDEBT # VERIF 4: all debt under limit
def sync(s, m): with dbm.open(s.n, 'c') as b: g0, g1, k = ecc.z2, ecc.i2b(1, 2), ecc.ecdsa() k.pt = k.uncompress(s.tid['PUB'] + s.tpk[s.tid['PUB']]) if k.verify(m[-96:], m[:-96]): if ecc.b2i(b[g0]) < ecc.b2i(m[:6]): b[g0] = m[:6] if len(m) == 116 and g1 in b: if ecc.b2i(b[g1]) < ecc.b2i(m[10:16]): b[g1] = m[10:16] if ecc.b2i(b[b'_'+g1]) < ecc.b2i(m[16:]): b[b'_'+g1] = m[16:20]
def server(s): t, n, buf, sdest = socket.socket(socket.AF_INET, socket.SOCK_DGRAM), now(), {}, ecc.i2b(0, 4) t.bind((HOST, s.p)) while (True): m = t.recvfrom(1024)[0] if now() - n <= 4: buf[m] = True else: n, buf = now(), {} z, dest, price = s.ear[m]+1 if m in s.ear else 0, m[-5:-1], ecc.b2i(m[-1:]) if s.current: s.cts[s.current] = m print (len(s.cts), s.short(m), z, len(buf), s.short(s.current)) if price > 0 and sdest != dest: print ('RECEIVE %d' % price) s.balance += price sdest = dest with dbm.open('db%d/hear'%s.p, 'c') as b: # heard ids s.ear[m], b[m] = z, ecc.i2b(now(), 4) + ecc.i2b(z, 4)
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 add(s, m): # 1 cross 2 tax 3 groups x, r, d, p, v = m[:10], m[:5], m[5:10], ecc.b2i(m[14:16]), ecc.b2i(m[10:13]) g0, g1 = ecc.z2, ecc.i2b(1, 2) print ('%s pays %d to %s' % (s.rvs[r], v, s.rvs[d])) with dbm.open(s.n, 'c') as b: t, u, w, y = v*TAX0//100, 0, 0, ecc.b2i(b[r]) if r in b else 0 if (x in b and p == ecc.b2i(b[x][3:])): w = ecc.b2i(b[x][:3]) else: assert x not in b and p == 0 q0, q1 = ecc.b2i(b[g0]), ecc.b2i(b[g1]) if g1 in b else 0 b[x] = ecc.i2b(w + v - (t+u), 3) + ecc.i2b(1 + p, 2) b[g0] = ecc.i2b(q0 + t, 6) if r+g1 in b: u = v*TAX1//100 b[g1] = ecc.i2b(q1 + u, 6) b[r] = ecc.i2b(y + t + u, 6) # t+u
def bal(s, p): # cross(p) - tax(p) + sum_groups (contrib*rate(p)) if s.rvs[p] == 'PUB' or len(s.tid) < 2: return 0 t, l, q0, q1 = fractions.Fraction(0), len(s.tid)-1, ecc.z2, ecc.i2b(1, 2) with dbm.open(s.n) as b: #assert len(s.tid) == ecc.b2i(b[b'_'+q0]) + 1 for x in [y for y in b.keys() if len(y) == MEKL and len(b[y]) == MEVL]: if p == x[:5]: t -= ecc.b2i(b[x][:3]) elif p == x[5:]: t += ecc.b2i(b[x][:3]) else: assert s.n == 'PUB' t -= ecc.b2i(b[p]) if p in b else 0 t += fractions.Fraction(ecc.b2i(b[q0]), l) if q1 in b and b'_' + q1 in b: r = ecc.b2i(b[p+q1]) if p + q1 in b else 0 t += fractions.Fraction(ecc.b2i(b[q1]) * r, ecc.b2i(b[b'_'+q1])) return t
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 !
def getb(x): return ecc.b2i(x[22:26])
def dump(s, b): f = open('db%d/dump'%s.p, 'bw') for i in b.keys(): f.write(i) # contacts for c in s.cts: f.write(c[:-1] + ecc.i2b(ecc.b2i(c[-1:]) + 0x10)) # contacts-contacts f.close()
def getn(x): return ecc.b2i(x[8:10])
def ttime(s): with dbm.open(s.n) as b: return sum([ ecc.b2i(b[x][3:]) for x in \ [y for y in b.keys() if len(y) == MEKL and len(b[y]) == MEVL]])
def getd(x): return ecc.b2i(x[26:30])
def getsk(s): with dbm.open(s.n) as b: return ecc.b2i(b[b'&']) # Authentication
def datdecode(t): return ecc.time.strftime('%d/%m/%y %H:%M:%S', ecc.time.localtime(float(ecc.b2i(t))))
def balance(x, d): "" n = ecc.b2i(d[x][:4]) if n == 0: return 0 return ecc.b2s(d[x + ecc.i2b(n, 4)][-14:-10], 4)