From 7b7e5c33caf38bae347afb27003ed7025ca01c66 Mon Sep 17 00:00:00 2001 From: poka Date: Fri, 20 Nov 2020 03:04:09 +0100 Subject: [PATCH] Sending message almost works ... --- dialog.py | 48 +++++++++++++--- lib/cesiumMessaging.py | 124 ++++++++++++++++++----------------------- 2 files changed, 96 insertions(+), 76 deletions(-) diff --git a/dialog.py b/dialog.py index d882e8a..9db9c1a 100755 --- a/dialog.py +++ b/dialog.py @@ -11,16 +11,50 @@ try: except: sys.stderr.write("Please fill the path to your private key (PubSec), and a Cesium ES address in userEnv.py\n") sys.exit(1) -from lib.cesiumMessaging import ReadFromCesium +from lib.cesiumMessaging import ReadFromCesium, SendToCesium # Parse arguments parser = argparse.ArgumentParser() -parser.add_argument('-n', '--number',type=int, default=3, help="Affiche les NUMBER derniers messages") -parser.add_argument('-o', '--outbox', action='store_true', help="Lecture des messages envoyés") + +subparsers = parser.add_subparsers() +read_cmd = subparsers.add_parser('read', help="Lecture des messages") +send_cmd = subparsers.add_parser('send', help="Envoi d'un message") + +if len(sys.argv) <= 1 or not sys.argv[1] in ('read','send'): + sys.stderr.write("Veuillez indiquer une commande valide:\n\n") + parser.print_help() + sys.exit(1) + +read_cmd.add_argument('-n', '--number',type=int, default=3, help="Affiche les NUMBER derniers messages") +read_cmd.add_argument('-o', '--outbox', action='store_true', help="Lit les messages de la boite d'envoi") + +send_cmd.add_argument('-d', '--destinataire', required=True, help="Destinataire du message") +send_cmd.add_argument('-t', '--titre', help="Titre du message à envoyer") +send_cmd.add_argument('-m', '--message', help="Message à envoyer") +send_cmd.add_argument('-f', '--fichier', help="Envoyer le message contenu dans le fichier 'FICHIER'") +send_cmd.add_argument('-o', '--outbox', action='store_true', help="Envoi le message sur la boite d'envoi") + + + args = parser.parse_args() -# Build ReadFromCesium object -messages = ReadFromCesium(dunikey, pod) -messages.read(args.number, args.outbox) -# print(messages.sendDocument(args.number, args.outbox)) # For debug, print complete JSON answer +# Build cesiumMessaging class +if sys.argv[1] == "read": + messages = ReadFromCesium(dunikey, pod) + messages.read(args.number, args.outbox) + # print(messages.sendDocument(args.number, args.outbox)) # For debug, print complete JSON answer +elif sys.argv[1] == "send": + if args.fichier: + with open(args.fichier, 'r') as f: + titre = f.readline() + msg = ''.join(f.read().splitlines(True)[0:]) + elif args.titre and args.message: + titre = args.titre + msg = args.message + else: + titre = input("Indiquez le titre du message: ") + msg = input("Indiquez le contenu du message: ") + + messages = SendToCesium(dunikey, pod, args.destinataire, args.outbox) + messages.send(titre, msg) diff --git a/lib/cesiumMessaging.py b/lib/cesiumMessaging.py index 6e3a6f8..d1fccfb 100755 --- a/lib/cesiumMessaging.py +++ b/lib/cesiumMessaging.py @@ -1,7 +1,8 @@ #!/usr/bin/env python3 -import os, sys, requests, json, base58, base64 -from natools import fmt, sign, get_privkey, box_decrypt +import os, sys, requests, json, base58, base64, time, string, random +from natools import fmt, sign, get_privkey, box_decrypt, box_encrypt +from hashlib import sha256 from datetime import datetime from termcolor import colored @@ -113,7 +114,7 @@ class ReadFromCesium: class SendToCesium: - def __init__(self, dunikey, pod): + def __init__(self, dunikey, pod, recipient, outbox): # Get my pubkey from my private key try: self.dunikey = dunikey @@ -123,83 +124,68 @@ class SendToCesium: self.issuer = get_privkey(dunikey, "pubsec").pubkey self.pod = pod + self.recipient = recipient + self.outbox = outbox - # Configure JSON document to send - def configDoc(self, nbrMsg, outbox): - if outbox: - boxType = "issuer" - else: - boxType = "recipient" - - return { - "sort": { "time": "desc" }, - "from": 0, - "size": nbrMsg, - "_source":[ - "issuer", - "recipient", - "title", - "content", - "time", - "nonce", - "read_signature" - ],"query":{ - "bool":{ - "filter":{ - "term":{ - boxType: self.issuer - } - } - } - } - } + # Generate pseudo-random nonce + nonce=[] + for i in range(32): + nonce.append(random.choice(string.ascii_letters + string.digits)) + self.nonce = ''.join(nonce) - def sendDocument(self, nbrMsg, outbox): - if outbox: + def encryptMsg(self, msg): + # nonce = base58.b58decode(nonce) + # self.title = base64.b64decode(msgSrc["title"]) + # self.title = box_decrypt(self.title, get_privkey(self.dunikey, "pubsec"), self.issuer, nonce).decode() + print(self.nonce) + nonce = base58.b58decode(self.nonce) + return box_encrypt(msg.encode(), get_privkey(self.dunikey, "pubsec"), self.issuer, nonce) + + + + def configDoc(self, title, msg): + # Get current timestamp + timeSent = int(time.time()) + + # Generate document to customize + document = str({"issuer":self.issuer,"recipient":self.recipient,"title":title,"content":msg,"time":timeSent,"nonce":self.nonce,"version":2}) + + # Generate hash of document + hashDoc = sha256(document.encode()).hexdigest().upper() + + # Generate signature of document + signature = fmt["64"](sign(hashDoc.encode(), get_privkey(self.dunikey, "pubsec"))[:-len(hashDoc.encode())]).decode() + + # Build final document + finalDoc = '{' + '"hash":"{0}","signature":"{1}",'.format(hashDoc, signature) + document[1:] + # document="{\"hash\":\"$hash\",\"signature\":\"$signature\",${hashBrut:1}" + + return finalDoc + + + def sendDocument(self, document): + if self.outbox: boxType = "outbox" else: boxType = "inbox" - document = json.dumps(self.configDoc(nbrMsg, outbox)) headers = { 'Content-type': 'application/json', } - # Send JSON document and get JSON result - result = requests.post('{0}/message/{1}/_search'.format(self.pod, boxType), headers=headers, data=document).json()["hits"] - return result - - # Parse JSON result and display messages - def readMessages(self, msgJSON, nbrMsg): - # Get terminal size - rows = int(os.popen('stty size', 'r').read().split()[1]) - - self.total = msgJSON["total"] - infoTotal = " Nombre de messages: " + str(nbrMsg) + "/" + str(self.total) + " " - print(colored(infoTotal.center(rows, '#'), "yellow")) - for hits in msgJSON["hits"]: - self.idMsg = hits["_id"] - msgSrc = hits["_source"] - self.issuer = msgSrc["issuer"] - nonce = msgSrc["nonce"] - nonce = base58.b58decode(nonce) - self.title = base64.b64decode(msgSrc["title"]) - self.title = box_decrypt(self.title, get_privkey(self.dunikey, "pubsec"), self.issuer, nonce).decode() - self.content = base64.b64decode(msgSrc["content"]) - self.content = box_decrypt(self.content, get_privkey(self.dunikey, "pubsec"), self.issuer, nonce).decode() - self.dateS = msgSrc["time"] - date = datetime.fromtimestamp(self.dateS).strftime(", le %d/%m/%Y à %H:%M ") - headerMsg = " De " + self.issuer + date + "(ID: {})".format(self.idMsg) + " " - - print('-'.center(rows, '-')) - print(colored(headerMsg, "blue").center(rows+9, '-')) - print('-'.center(rows, '-')) - print("Objet: " + self.title) - print(self.content) + # Send JSON document and get result + try: + result = requests.post('{0}/message/{1}?pubkey={2}'.format(self.pod, boxType, self.recipient), headers=headers, data=document) + except Exception as e: + sys.stderr.write("Impossible d'envyer le message:\n" + str(e)) + sys.exit(1) + else: + print(result) + return result - def read(self, nbrMsg, outbox): - jsonMsg = self.sendDocument(nbrMsg, outbox) - self.readMessages(jsonMsg, nbrMsg) + def send(self, title, msg): + finalDoc = self.configDoc(self.encryptMsg(title), self.encryptMsg(msg)) # Configure JSON document to send + self.sendDocument(finalDoc) # Send final signed document