From 82845a2f4a293947c99779888afeb0033dcb5b68 Mon Sep 17 00:00:00 2001 From: qo-op Date: Mon, 4 May 2020 21:58:04 +0100 Subject: [PATCH] G1pub --- g1sms/tools/duniter_getnode.sh | 107 ++++++++++++++++++++++++++++ g1sms/tools/key_create_dunikey.py | 28 ++++++++ g1sms/tools/natools.py | 112 ++++++++++++++++++++++++++++++ 3 files changed, 247 insertions(+) create mode 100755 g1sms/tools/duniter_getnode.sh create mode 100755 g1sms/tools/key_create_dunikey.py create mode 100755 g1sms/tools/natools.py diff --git a/g1sms/tools/duniter_getnode.sh b/g1sms/tools/duniter_getnode.sh new file mode 100755 index 0000000..ee64230 --- /dev/null +++ b/g1sms/tools/duniter_getnode.sh @@ -0,0 +1,107 @@ +#!/bin/bash +################################################################################ +# Authors: @jytou (https://git.duniter.org/jytou) +# Modified by Fred (support@qo-op.com) +# Version: 0.1 +# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/) +################################################################################ +# Checks the current block number of $DIR/duniter_nodes.txt (is run in parallel) +# and output random (from last synchronized) node + +checkonenode() +{ + # Timeout in seconds for https nodes + httpsTimeout=1 + # Timeout in seconds for http nodes + httpTimeout=1 + + node=$1 + watched=$2 + outfile=$3 + # Curl: -m timeout, -k ignore SSL certificate errors + cur=`echo "$( { curl -m $httpsTimeout -k https://$node/blockchain/current; } 2>&1 )"` + n=$node + if [[ "$cur" != *issuersFrameVar* ]] + then + # It failed in https, maybe try http? + cur=`echo "$( { curl -m $httpTimeout http://$node/blockchain/current; } 2>&1 )"` + if [[ "$cur" == *issuersFrameVar* ]] + then + # Indicate that the node is http + n="$n-(http)" + fi + fi + if [[ "$cur" != *issuersFrameVar* ]] + then + # The node didn't respond on time + cur="ERROR" + else + # The node did respond - grab the block number and hash of the block as key + cur="`echo "$cur"|grep '^ "number": '|awk '{print $2}'|awk -F, '{print $1}'`-`echo "$cur"|grep '^ "hash": '|awk '{print $2}'|awk '{print substr($1,2,13)}'`" + fi + if [[ $watched =~ .*#$node#.* ]] + then + # The node is a watched node, add some bold + n="\e[1m$n\e[0m" + fi + # Put the result into the file + echo "$cur $n">$outfile + # Notify that we're done here + touch $outfile.done +} + +# Temp dir where results are stored +rm -Rf /tmp/zen/gnodewatch +DIR=/tmp/zen/gnodewatch +export DIR +mkdir -p $DIR/chains + +##### $DIR/duniter_nodes.txt REFRESH after 20 minutes ##### +find $DIR/ -cmin +20 -type f -name "duniter_*" -exec rm -f '{}' \; +if [[ ! -f $DIR/duniter_nodes.txt ]]; then + # Get New BMAS known Nodes list from shuffle one $DIR/good.nodes.txt + [[ -f $DIR/good.nodes.txt ]] && DUNITER=$(shuf -n 1 $DIR/good.nodes.txt) || DUNITER="duniter-g1.p2p.legal:443" + curl -s https://$DUNITER/network/peers | jq '.peers[] | .endpoints' | grep BMAS | awk '{print $2,$3}' | sed s/\"//g | sed s/\,//g | sed s/\ /:/g > $DIR/duniter_nodes.txt +fi + +# Grab the nodes we are actively watching - they will be in bold in the final output +watched=`grep -v "#" $DIR/duniter_nodes.txt|egrep "\!$"|awk '{print "#" $1 "#"}'` +# All nodes we are watching +nodes=`grep -v "#" $DIR/duniter_nodes.txt|awk '{print $1}'` +# The index to generate separate file names +index=0 +# Wipe out the output directory +rm $DIR/*out $DIR/*done $DIR/chains/* $DIR/NODE.* 2>/dev/null + +# Query all nodes in parallel +for node in $nodes +do + checkonenode $node "$watched" $DIR/$index.out & + ((index++)) +done + +# Wait a little for the first files to be created +sleep 1s +# Wait for all the threads to report they are done +while [ `ls $DIR/*done|wc -l` -lt $index ] +do + sleep 1s +done + +# Grab all results +curs=`cat $DIR/*out|sort` +# Extract all forks, excluding all errors +chains="`echo "$curs"|grep -v ERROR|awk '{print $1}'|sort -r|uniq`" + +# Count the number of chains and output most recent consensus to "good.nodes.txt" +nb=0 +for chain in $chains +do + echo "$curs" | egrep "^$chain " | awk '{print $2}' >> $DIR/chains/$nb; + ((nb++)) +done + +longchain=$(ls -S $DIR/chains/ | head -n 1) +cp $DIR/chains/$longchain $DIR/good.nodes.txt +# WRITE OUT shuffle Duniter Node Sync with longest chain +echo $(shuf -n 1 $DIR/good.nodes.txt) diff --git a/g1sms/tools/key_create_dunikey.py b/g1sms/tools/key_create_dunikey.py new file mode 100755 index 0000000..32720c8 --- /dev/null +++ b/g1sms/tools/key_create_dunikey.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 +# This Python script gets Duniter creddentials as arguments, and writes a PubSec file that should be compatible with Cesium and Silkaj(DuniterPy) clients. +# launch with : +# python3 key_create_dnuikey.py + +# depends on duniterpy 0.56 + +### Licence - WTFPL +# This script was written my Matograine, in the hope that it will be helpful. +# Do What The Fuck you like with it. There is : +# * no guarantee that this will work +# * no support of any kind +# +# If this is helpful, please consider making a donation to the developper's pubkey : 78ZwwgpgdH5uLZLbThUQH7LKwPgjMunYfLiCfUCySkM8 +# Have fun + +from sys import argv +from duniterpy.key import SigningKey + +# path to save to +path = "/tmp/secret.dunikey" + +key = SigningKey.from_credentials(argv[1], argv[2], None) +key.save_pubsec_file(path) +print( + "G1 Wallet: ", + key.pubkey, +) diff --git a/g1sms/tools/natools.py b/g1sms/tools/natools.py new file mode 100755 index 0000000..9b6470f --- /dev/null +++ b/g1sms/tools/natools.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python3 + +""" + CopyLeft 2020 Pascal Engélibert + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +""" + +import os, sys, duniterpy.key, libnacl.sign + +def getargv(arg:str, default:str="", n:int=1, args:list=sys.argv) -> str: + if arg in args and len(args) > args.index(arg)+n: + return args[args.index(arg)+n] + else: + return default + +def read_data(data_path, b=True): + if data_path == "-": + if b: + return sys.stdin.read().encode() + else: + return sys.stdin.read() + else: + return open(os.path.expanduser(data_path), "rb" if b else "r").read() + +def write_data(data, result_path): + if result_path == "-": + sys.stdout.write(data.decode()) + else: + open(os.path.expanduser(result_path), "wb").write(data) + +def encrypt(data, pubkey): + return duniterpy.key.PublicKey(pubkey).encrypt_seal(data) + +def decrypt(data, privkey): + return privkey.decrypt_seal(data) + +def sign(data, privkey): + return privkey.sign(data) + +def verify(data, pubkey): + try: + sys.stderr.write("Signature OK!\n") + return libnacl.sign.Verifier(duniterpy.key.PublicKey(pubkey).hex_pk()).verify(data) + except ValueError: + sys.stderr.write("Bad signature!\n") + exit(1) + +def get_privkey(privkey_path, pubsec): + if pubsec: + return duniterpy.key.SigningKey.from_pubsec_file(privkey_path) + else: + return duniterpy.key.SigningKey.from_seedhex(read_data(privkey_path, False)) + +def show_help(): + print("""Usage: +python3 natools.py [options] + +Commands: + encrypt Encrypt data + decrypt Decrypt data + sign Sign data + verify Verify data + +Options: + -i Input file path (default: -) + -k Privkey file path (default: authfile.key) + --pubsec Use pub/sec format for -p + -p Pubkey (base58) + -o Output file path (default: -) + +Note: "-" means stdin or stdout. +""") + +if __name__ == "__main__": + + if "--help" in sys.argv: + show_help() + exit() + + data_path = getargv("-i", "-") + privkey_path = getargv("-k", "authfile.key") + pubsec = "--pubsec" in sys.argv + pubkey = getargv("-p") + result_path = getargv("-o", "-") + + try: + if sys.argv[1] == "encrypt": + write_data(encrypt(read_data(data_path), pubkey), result_path) + elif sys.argv[1] == "decrypt": + write_data(decrypt(read_data(data_path), get_privkey(privkey_path, pubsec)), result_path) + elif sys.argv[1] == "sign": + write_data(sign(read_data(data_path), get_privkey(privkey_path, pubsec)), result_path) + elif sys.argv[1] == "verify": + write_data(verify(read_data(data_path), pubkey), result_path) + else: + show_help() + except Exception as e: + sys.stderr.write("Error: {}\n".format(e)) + show_help() + exit(1)