Compare commits
No commits in common. "master" and "master" have entirely different histories.
|
@ -1,6 +0,0 @@
|
||||||
.env
|
|
||||||
*.pyc
|
|
||||||
tmp/
|
|
||||||
_images/
|
|
||||||
DICE
|
|
||||||
♥Box
|
|
436
G1BILLETS.sh
|
@ -1,398 +1,60 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
################################################################################
|
################################################################################
|
||||||
# Author: Fred (support@qo-op.com)
|
# Author: Fred (support@qo-op.com)
|
||||||
# Version: 1.0
|
# Version: 0.1
|
||||||
# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/)
|
# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/)
|
||||||
################################################################################
|
################################################################################
|
||||||
MY_PATH="`dirname \"$0\"`" # relative
|
MY_PATH="`dirname \"$0\"`" # relative
|
||||||
MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized
|
MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized
|
||||||
ME="${0##*/}"
|
ME="${0##*/}"
|
||||||
|
|
||||||
## LOAD PERSONAL OR DEFAULT STYLES
|
|
||||||
[[ -d ${MY_PATH}/_images/_/ ]] \
|
|
||||||
&& IMAGES="_images" \
|
|
||||||
|| IMAGES="images"
|
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
# Create different king of G1BILLET(s) with $MONTANT DU or TW IPNS + ZENCARD
|
# Create and print 6 G1Billets de $MONTANT DU
|
||||||
# ${MY_PATH}/G1BILLETS.sh 5 ticket 2 # MONTANT # STYLE # SECURITE
|
# ${MY_PATH}/G1BILLETS.sh 5 986397643
|
||||||
################################################################################
|
################################################################################
|
||||||
MONTANT="$1"
|
MONTANT="$1"
|
||||||
|
UNIQID="$2"
|
||||||
### COMMAND LINE MODE (DAEMON IS CALLING ITSELF) ###
|
STYLE="$3"
|
||||||
if [[ $MONTANT != "daemon" ]]; then
|
|
||||||
|
## PLANCHE DE 6 BILLETS PAR DEFAUT
|
||||||
pidportinuse=$(lsof -i :33102 | tail -n 1 | awk '{print $2}')
|
NBbillets=6
|
||||||
[[ $pidportinuse ]] && kill $pidportinuse && echo "KILLING NOT COLLECTED THREAD $pidportinuse"
|
|
||||||
|
[[ $MONTANT == "" ]] && MONTANT="___"
|
||||||
[[ $MONTANT == "" || $MONTANT == "0" ]] && MONTANT="___"
|
[[ $UNIQID == "" ]] && UNIQID=$(date -u +%s%N | cut -b1-13)$RANDOM
|
||||||
|
[[ "$STYLE" == "xbian" ]] && NBbillets=1 ## STYLE=xbian => 1 BILLET
|
||||||
STYLE="$2"
|
[[ "$STYLE" == "1" ]] && NBbillets=1 && STYLE="" ## 1 BILLET
|
||||||
|
|
||||||
DICE="$3"
|
# CHECK IF $STYLE IMAGES EXIST
|
||||||
|
[[ ! -f ${MY_PATH}/images/fond${STYLE}.jpg ]] && exit 1
|
||||||
SECRET1="$4"
|
[[ ! -f ${MY_PATH}/images/g1${STYLE}.png ]] && exit 1
|
||||||
SECRET2="$5"
|
[[ ! -f ${MY_PATH}/images/logo${STYLE}.png ]] && exit 1
|
||||||
|
|
||||||
[[ $DICE != ?(-)+([0-9]) ]] && DICE=$(cat $MY_PATH/DICE 2>/dev/null) ## HOW MANY WORDS SECRETS
|
# CREATION DE $NBbillets BILLETS DE $MONTANT DU
|
||||||
[[ $DICE != ?(-)+([0-9]) ]] && DICE=4
|
boucle=0;
|
||||||
|
while [ $boucle -lt $NBbillets ]
|
||||||
echo "G1BILLET FACTORY MONTANT=$MONTANT DICE=$DICE"
|
do
|
||||||
echo "$STYLE : $MY_PATH/${IMAGES}/$STYLE"
|
boucle=$((boucle+1))
|
||||||
|
NUMBER=$(${MY_PATH}/diceware.sh 4 | xargs)
|
||||||
## CHECK IF STYLE IS EMAIL => ZENCARD+@ IPFS G1BILLET
|
SECRET=$(${MY_PATH}/diceware.sh 4 | xargs)
|
||||||
if [[ "${STYLE}" =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$ ]]; then
|
|
||||||
|
# CREATION CLEF BILLET
|
||||||
echo "ASTROPORT $STYLE :: ZENCARD+@"
|
BILLETPUBKEY=$(python3 ${MY_PATH}/key_create_dunikey.py "$NUMBER" "$SECRET")
|
||||||
# echo "PLAYER : $STYLE"
|
rm -f /tmp/secret.dunikey
|
||||||
EMAIL=${STYLE}
|
|
||||||
DICE=5
|
mkdir -p "/tmp/g1billet/${UNIQID}"
|
||||||
|
# CREATION FICHIER IMAGE BILLET
|
||||||
## DEFAULT xZSTYLE
|
$(${MY_PATH}/MAKE_G1BILLET.sh "${NUMBER}" "${SECRET}" "${MONTANT}" "${BILLETPUBKEY}" "${UNIQID}" "${STYLE}")
|
||||||
LASTX=$(ls -d ${MY_PATH}/${IMAGES}/x* | tail -n 1)
|
|
||||||
STYLE="$(echo ${LASTX} | rev | cut -d '/' -f 1 | rev)"
|
done
|
||||||
|
|
||||||
fi
|
# MONTAGE DES IMAGES DES BILLETS VERS /tmp/g1billet/${UNIQID}.pdf
|
||||||
|
montage /tmp/g1billet/${UNIQID}/*.jpg -tile 2x3 -geometry 964x459 /tmp/g1billet/${UNIQID}.pdf
|
||||||
## STYLE SELECTED: PDF DE 6 BILLETS OR SINGLE
|
# NB!! if "not autorized" then edit /etc/ImageMagick-6/policy.xml and comment
|
||||||
[[ "${STYLE:0:1}" != "_" ]] && NBbillets=1 && MONTANT="___" ## NOT DEFAULT (empty or _ style)
|
# <!-- <policy domain="coder" rights="none" pattern="PDF" /> -->
|
||||||
[[ ${STYLE} == "" || ${STYLE} == "_" ]] && NBbillets=6 && STYLE="_" # 6 x G1BILLET v1 = "MLC"
|
|
||||||
|
# CLEANING TEMP FILES
|
||||||
echo "G1BILLET MAKE $NBbillets - ${STYLE} (${DICE}) - "
|
rm -Rf /tmp/g1billet/${UNIQID}
|
||||||
|
|
||||||
# CHECK IF $STYLE IMAGES EXIST
|
# ALLOWS ANY USER TO DELETE
|
||||||
IMAGESSTYLE="${IMAGES}/${STYLE}"
|
chmod 777 /tmp/g1billet/${UNIQID}.pdf
|
||||||
[[ ${STYLE} == "UPlanet" ]] && STYLE="xastro" ## DEFAULT : UPlanet Style
|
|
||||||
[[ ! -f ${MY_PATH}/${IMAGES}/${STYLE}/g1.png ]] && ERROR="MISSING ./${IMAGES}/${STYLE}/g1.png - EXIT" && echo $ERROR && exit 1
|
exit
|
||||||
[[ ! -f ${MY_PATH}/${IMAGES}/${STYLE}/fond.jpg ]] && ERROR="MISSING ./${IMAGES}/${STYLE}/fond.jpg- EXIT" && echo $ERROR && exit 1
|
|
||||||
[[ ! -f ${MY_PATH}/${IMAGES}/${STYLE}/logo.png ]] && ERROR="MISSING ./${IMAGES}/${STYLE}/logo.png- EXIT" && echo $ERROR && exit 1
|
|
||||||
|
|
||||||
# CREATION DE $NBbillets BILLETS DE $MONTANT DU
|
|
||||||
boucle=0;
|
|
||||||
while [ $boucle -lt $NBbillets ]
|
|
||||||
do
|
|
||||||
## THIS IS THE PASS for ZENCARD
|
|
||||||
if [[ ${boucle} == 0 ]]; then
|
|
||||||
UNIQID=$(echo "${RANDOM}${RANDOM}${RANDOM}${RANDOM}" | tail -c-5)
|
|
||||||
[ $DICE -gt 4 ] && UNIQID=$(echo "${RANDOM}${RANDOM}${RANDOM}${RANDOM}" | tail -c-7)
|
|
||||||
[ $DICE -gt 6 ] && UNIQID=$(${MY_PATH}/diceware.sh 1 | xargs)$(echo "${RANDOM}${RANDOM}" | tail -c-7)
|
|
||||||
mkdir -p "${MY_PATH}/tmp/g1billet/${UNIQID}"
|
|
||||||
fi
|
|
||||||
boucle=$((boucle+1))
|
|
||||||
|
|
||||||
## ADAPT SECURITY LEVEL
|
|
||||||
[[ ${SECRET1} == "" || $boucle -gt 1 ]] && SECRET1="${UNIQID} $(${MY_PATH}/diceware.sh $DICE | xargs)"
|
|
||||||
[[ ${SECRET2} == "" || $boucle -gt 1 ]] && SECRET2=$(${MY_PATH}/diceware.sh $DICE | xargs)
|
|
||||||
echo "${SECRET1}" "${SECRET2}"
|
|
||||||
# CREATION CLEF BILLET
|
|
||||||
BILLETPUBKEY=$(python3 ${MY_PATH}/key_create_dunikey.py "${SECRET1}" "${SECRET2}")
|
|
||||||
rm -f /tmp/secret.dunikey
|
|
||||||
echo "$boucle : $BILLETPUBKEY "
|
|
||||||
|
|
||||||
if [[ $DICE -ge 4 || "${STYLE:0:1}" != "_" ]]; then
|
|
||||||
# + ASTRONS ## G1BILLET APP STICKER
|
|
||||||
ASTRONS=$(${MY_PATH}/keygen -t ipfs "${SECRET1}" "${SECRET2}")
|
|
||||||
echo "/ipns/$ASTRONS" # 12D3Koo style - QRCODE ipfs2g1 verify
|
|
||||||
fi
|
|
||||||
#######################################################################################################
|
|
||||||
# CREATION FICHIER IMAGE BILLET dans ${MY_PATH}/tmp/g1billet/${UNIQID}
|
|
||||||
#######################################################################################################
|
|
||||||
echo ${MY_PATH}/MAKE_G1BILLET.sh '"'${SECRET1}'"' '"'${SECRET2}'"' "${MONTANT}" "${BILLETPUBKEY}" "${UNIQID}" "${STYLE}" "${ASTRONS}" "${EMAIL}"
|
|
||||||
${MY_PATH}/MAKE_G1BILLET.sh "${SECRET1}" "${SECRET2}" "${MONTANT}" "${BILLETPUBKEY}" "${UNIQID}" "${STYLE}" "${ASTRONS}" "${EMAIL}"
|
|
||||||
#######################################################################################################
|
|
||||||
#######################################################################################################
|
|
||||||
|
|
||||||
done
|
|
||||||
|
|
||||||
if [[ ${NBbillets} == 1 ]]; then
|
|
||||||
|
|
||||||
# ONE FILE ONLY
|
|
||||||
cp ${MY_PATH}/tmp/g1billet/${UNIQID}/*.jpg ${MY_PATH}/tmp/g1billet/${UNIQID}.jpg
|
|
||||||
|
|
||||||
# CLEANING TEMP FILES
|
|
||||||
echo rm -Rf ${MY_PATH}/tmp/g1billet/${UNIQID}
|
|
||||||
|
|
||||||
# ALLOWS ANY USER TO DELETE
|
|
||||||
chmod 777 ${MY_PATH}/tmp/g1billet/${UNIQID}.jpg
|
|
||||||
export ZFILE="${MY_PATH}/tmp/g1billet/${UNIQID}.jpg"
|
|
||||||
|
|
||||||
else
|
|
||||||
|
|
||||||
# MONTAGE DES IMAGES DES BILLETS VERS ${MY_PATH}/tmp/g1billet/${UNIQID}.pdf
|
|
||||||
montage ${MY_PATH}/tmp/g1billet/${UNIQID}/*.jpg -tile 2x3 -geometry 964x459 ${MY_PATH}/tmp/g1billet/${UNIQID}.pdf
|
|
||||||
# NB!! if "not autorized" then edit /etc/ImageMagick-6/policy.xml and comment
|
|
||||||
[[ ! -s ${MY_PATH}/tmp/g1billet/${UNIQID}.pdf ]] && echo "ERROR PDF NOT FOUND - contact - support@qo-op.com" && exit 1
|
|
||||||
# <!-- <policy domain="coder" rights="none" pattern="PDF" /> -->
|
|
||||||
|
|
||||||
# CLEANING TEMP FILES
|
|
||||||
rm -Rf ${MY_PATH}/tmp/g1billet/${UNIQID}
|
|
||||||
|
|
||||||
# ALLOWS ANY USER TO DELETE
|
|
||||||
chmod 777 ${MY_PATH}/tmp/g1billet/${UNIQID}.pdf
|
|
||||||
export ZFILE="${MY_PATH}/tmp/g1billet/${UNIQID}.pdf"
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
###########################################################################
|
|
||||||
[[ $XDG_SESSION_TYPE == 'x11' ]] && xdg-open "$ZFILE"
|
|
||||||
###########################################################################
|
|
||||||
echo "$ZFILE" # IMPORTANT ## LAST LINE : INFORM DAEMON
|
|
||||||
###########################################################################
|
|
||||||
|
|
||||||
else
|
|
||||||
################################################################################
|
|
||||||
################################################################################
|
|
||||||
## MAKE IT A NETWORK MICRO SERVICE -- PORTS : INPUT=33101 OUTPUT=33102
|
|
||||||
############## CLEAN START DAEMON MODE ###
|
|
||||||
pidportinuse=$(lsof -i :33101 | tail -n 1 | awk '{print $2}')
|
|
||||||
[[ $pidportinuse ]] && echo "KILLING OLD DEAMON 33101 $pidportinuse" && kill -9 $pidportinuse && killall G1BILLETS.sh && exit 1
|
|
||||||
|
|
||||||
pidportinuse=$(lsof -i :33102 | head -n 1 | awk '{print $2}')
|
|
||||||
[[ $pidportinuse ]] && kill $pidportinuse && echo "KILLING NOT COLLECTED THREAD $pidportinuse"
|
|
||||||
#####################################################################
|
|
||||||
myIP=$(hostname -I | awk '{print $1}' | head -n 1)
|
|
||||||
isLAN=$(route -n |awk '$1 == "0.0.0.0" {print $2}' | grep -E "/(^127\.)|(^192\.168\.)|(^10\.)|(^172\.1[6-9]\.)|(^172\.2[0-9]\.)|(^172\.3[0-1]\.)|(^::1$)|(^[fF][cCdD])/")
|
|
||||||
isBOX=$(cat ${MY_PATH}/♥Box)
|
|
||||||
|
|
||||||
## WHERE DO CLIENT WILL GET FILE
|
|
||||||
if [[ $isLAN ]]; then
|
|
||||||
HNAME="http://g1billet.localhost"
|
|
||||||
else
|
|
||||||
HNAME="http://$(hostname -I | awk '{print $1}' | head -n 1)"
|
|
||||||
fi
|
|
||||||
RNAME="$HNAME:33102"
|
|
||||||
[[ $isBOX != "" ]] && RNAME="$isBOX"
|
|
||||||
|
|
||||||
## AVAILABLE STYLES : CREATING SELECT
|
|
||||||
sytle=($(find ${MY_PATH}/${IMAGES}/* -type d | sort | rev | cut -d '/' -f 1 | rev))
|
|
||||||
sytlenb=${#sytle[@]}
|
|
||||||
OPT=""
|
|
||||||
for stname in ${sytle[@]}; do
|
|
||||||
|
|
||||||
pre=${stname:0:1}
|
|
||||||
|
|
||||||
if [[ $pre == "_" ]]; then
|
|
||||||
OPT="${OPT}<option value='_'>:: G1BILLET :: (+) ::</option>"
|
|
||||||
elif [[ $pre == "x" ]]; then
|
|
||||||
OPT="${OPT}<option value='${stname}'>:: ZENCARD+TW :: ${stname} ::</option>"
|
|
||||||
elif [[ $(echo ${stname} | grep '@') && -s ~/.zen/Astroport.ONE/tools/VOEUX.print.sh ]]; then
|
|
||||||
OPT="${OPT}<option value='${stname}'>:: ZENCARD+@ :: ${stname} ::</option>"
|
|
||||||
else
|
|
||||||
OPT="${OPT}<option value='${stname}'>:: ZENCARD :: ${stname} ::</option>"
|
|
||||||
fi
|
|
||||||
|
|
||||||
done
|
|
||||||
|
|
||||||
## WELCOME HTTP / HTML PAGE
|
|
||||||
HTTPWELLCOME='HTTP/1.1 200 OK
|
|
||||||
Access-Control-Allow-Origin: *
|
|
||||||
Access-Control-Allow-Credentials: true
|
|
||||||
Access-Control-Allow-Methods: GET
|
|
||||||
Server: Astroport
|
|
||||||
Content-Type: text/html; charset=UTF-8
|
|
||||||
|
|
||||||
<!DOCTYPE html><html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>[G1BILLET] HTTP MICRO SERVICE - 33101 - 33102 -</title>
|
|
||||||
<meta http-equiv="refresh" content="30; url='$RNAME'" />
|
|
||||||
<style>
|
|
||||||
#countdown { display: flex; justify-content: center; align-items: center; color: #0e2c4c; font-size: 20px; width: 60px; height: 60px; background-color: #e7d9fc; border-radius: 50%;}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<center><h1><a href="'$RNAME'">(♥‿‿♥)</a>.</h1></center>
|
|
||||||
<center><div id="countdown"></div></center>
|
|
||||||
<script>
|
|
||||||
var timeLeft = 30;
|
|
||||||
var elem = document.getElementById("countdown");
|
|
||||||
var timerId = setInterval(countdown, 1000);
|
|
||||||
|
|
||||||
function countdown() {
|
|
||||||
if (timeLeft == -1) {
|
|
||||||
clearTimeout(timerId);
|
|
||||||
doSomething();
|
|
||||||
} else {
|
|
||||||
elem.innerHTML = timeLeft + " s";
|
|
||||||
timeLeft--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<center>
|
|
||||||
<form method="get">
|
|
||||||
<br>
|
|
||||||
|
|
||||||
<label for="montant">Montant :</label>
|
|
||||||
<select name="montant">
|
|
||||||
<option value="0">_</option>
|
|
||||||
<option value="1">1</option>
|
|
||||||
<option value="2">2</option>
|
|
||||||
<option value="5">5</option>
|
|
||||||
<option value="10">10</option>
|
|
||||||
<option value="20">20</option>
|
|
||||||
<option value="50">50</option>
|
|
||||||
<option value="100">100</option>
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<label for="type">Type :</label>
|
|
||||||
<select name="type">
|
|
||||||
<option value=''></option>
|
|
||||||
'${OPT}'
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<label for="dice">Dice :</label>
|
|
||||||
<select name="dice">
|
|
||||||
<option value="1">1</option>
|
|
||||||
<option value="2">2</option>
|
|
||||||
<option value="3">3</option>
|
|
||||||
<option value="4" selected>4</option>
|
|
||||||
<option value="5">5</option>
|
|
||||||
<option value="6">6</option>
|
|
||||||
<option value="7">7</option>
|
|
||||||
</select>
|
|
||||||
<br> <br>
|
|
||||||
<button type="submit">Lancer Fabrication</button>
|
|
||||||
</form>
|
|
||||||
</center>
|
|
||||||
</body></html>'
|
|
||||||
|
|
||||||
function urldecode() { : "${*//+/ }"; echo -e "${_//%/\\x}"; }
|
|
||||||
|
|
||||||
#### LOG REDIRECTION
|
|
||||||
echo "=================================================="
|
|
||||||
echo "G1BILLET x 6 : $HNAME:33101"
|
|
||||||
echo "G1BILLET+ x 6 : $HNAME:33101/?montant=0&style=_&dice=4"
|
|
||||||
echo "ZENCARD : $HNAME:33101/?montant=10&style=saubole"
|
|
||||||
echo "ZENCARD+TW : $HNAME:33101/?montant=0&style=astro${RANDOM}@yopmail.com"
|
|
||||||
echo "=================================================="
|
|
||||||
echo "LOG : tail -f ${MY_PATH}/tmp/G1BILLETS.log"
|
|
||||||
echo "=================================================="
|
|
||||||
mkdir -p ${MY_PATH}/tmp
|
|
||||||
exec 2>&1 >> ${MY_PATH}/tmp/G1BILLETS.log
|
|
||||||
|
|
||||||
#####################################################################
|
|
||||||
########### daemon loop
|
|
||||||
#####################################################################
|
|
||||||
while true; do
|
|
||||||
echo "============= ************ =========================="
|
|
||||||
echo " STARTING $ME DAEMON READY $(date)"
|
|
||||||
echo "============= ************ =========================="
|
|
||||||
|
|
||||||
REQ=$(echo "$HTTPWELLCOME" | nc -l -p 33101 -q 1) ## # WAIT FOR 33101 PORT CONTACT
|
|
||||||
|
|
||||||
MOATS=$(date -u +"%Y%m%d%H%M%S%4N")
|
|
||||||
start=`date +%s`
|
|
||||||
|
|
||||||
URL=$(echo "$REQ" | grep '^GET' | cut -d ' ' -f2 | cut -d '?' -f2)
|
|
||||||
HOSTP=$(echo "$REQ" | grep '^Host:' | cut -d ' ' -f2 | cut -d '?' -f2)
|
|
||||||
HOST=$(echo "$HOSTP" | cut -d ':' -f 1)
|
|
||||||
|
|
||||||
echo "=================================================="
|
|
||||||
echo "$ME RUN $(date)"
|
|
||||||
echo "=========== %%%%%%%%%%%%%%% =============="
|
|
||||||
echo "$REQ"
|
|
||||||
echo "=========== %%%%%%%%%%%%%%% =============="
|
|
||||||
echo "$URL"
|
|
||||||
echo "=================================================="
|
|
||||||
|
|
||||||
## DECODING RECEIVED URL
|
|
||||||
arr=(${URL//[=&]/ })
|
|
||||||
# PARAM (x 3) EXTRACT "¶m=value"
|
|
||||||
ONE=$(urldecode ${arr[0]} | xargs); TWO=$(urldecode ${arr[2]} | xargs); X=$(urldecode ${arr[4]} | xargs);
|
|
||||||
MONTANT=$(urldecode ${arr[1]} | xargs); STYLE=$(urldecode ${arr[3]} | xargs); XPARM=$(urldecode ${arr[5]} | xargs);
|
|
||||||
echo "DECODED : $ONE=$MONTANT & $TWO=$STYLE & $X=$XPARM"
|
|
||||||
|
|
||||||
[[ $STYLE == "dice" ]] && STYLE="_" && XPARM=$X ## /?montant=0&type=&dice=1
|
|
||||||
|
|
||||||
# EXECUTE COMMAND
|
|
||||||
#####################################################################
|
|
||||||
echo ${MY_PATH}/${ME} '"'$MONTANT'"' '"'$STYLE'"' '"'$XPARM'"'
|
|
||||||
#####################################################################
|
|
||||||
# EXECUTE COMMAND
|
|
||||||
|
|
||||||
LOG=$(${MY_PATH}/${ME} "$MONTANT" "$STYLE" "$XPARM")
|
|
||||||
echo "$LOG"
|
|
||||||
# EXTRACT VALUES FROM SELF LOG
|
|
||||||
IPNS=$(echo "$LOG" | grep '/ipns/')
|
|
||||||
[[ $IPNS ]] && echo "TW IPNS : $IPNS"
|
|
||||||
CURL=$(echo "$LOG" | grep -w curl)
|
|
||||||
[[ $IPNS ]] && echo "LIEN ACTIVATION : $CURL"
|
|
||||||
echo "=========" ## LAST LINE INFORMATION
|
|
||||||
ZFILE=$(echo "$LOG" | tail -n 1) ### LAST LINE : INFORM DAEMON
|
|
||||||
echo $ZFILE
|
|
||||||
echo "========="
|
|
||||||
|
|
||||||
### AUCUN RESULTAT
|
|
||||||
if [[ ! -s $ZFILE ]]; then
|
|
||||||
(
|
|
||||||
echo "HTTP/1.1 200 OK
|
|
||||||
Access-Control-Allow-Origin: ${myASTROPORT}
|
|
||||||
Access-Control-Allow-Credentials: true
|
|
||||||
Access-Control-Allow-Methods: GET
|
|
||||||
Server: Astroport.ONE
|
|
||||||
Content-Type: text/html; charset=UTF-8
|
|
||||||
|
|
||||||
<h1>ERROR $ZFILE</h1>" | nc -l -p 33102 -q 1 > /dev/null 2>&1 \
|
|
||||||
&& rm -f "${MY_PATH}/tmp/http.${MOATS}"
|
|
||||||
) &
|
|
||||||
|
|
||||||
else ## FILE IS FOUND
|
|
||||||
|
|
||||||
# PREPARE FILE SENDING
|
|
||||||
FILE_NAME="$(basename "${ZFILE}")"
|
|
||||||
EXT="${FILE_NAME##*.}"
|
|
||||||
BSIZE=$(du -b "${ZFILE}" | awk '{print $1}' | tail -n 1)
|
|
||||||
|
|
||||||
# KILL OLD 33102 - USE IT IF YOU ( publishing )&
|
|
||||||
pidportinuse=$(lsof -i :33102 | tail -n 1 | awk '{print $2}')
|
|
||||||
[[ $pidportinuse ]] && kill -9 $pidportinuse && echo "KILLING NOT COLLECTED THREAD $pidportinuse"
|
|
||||||
|
|
||||||
# HTTP/1.1 200 OK
|
|
||||||
echo 'HTTP/1.1 200 OK
|
|
||||||
Access-Control-Allow-Origin: *
|
|
||||||
Access-Control-Allow-Credentials: true
|
|
||||||
Access-Control-Allow-Methods: GET
|
|
||||||
Server: Astroport.G1BILLET
|
|
||||||
Cache-Control: public
|
|
||||||
Content-Transfer-Encoding: Binary
|
|
||||||
Content-Length:'${BSIZE}'
|
|
||||||
Content-Disposition: attachment; filename='${FILE_NAME}'
|
|
||||||
' > ${MY_PATH}/tmp/http.${MOATS}
|
|
||||||
|
|
||||||
cat ${ZFILE} >> ${MY_PATH}/tmp/http.${MOATS}
|
|
||||||
|
|
||||||
# NETCAT PUBLISH port=33102
|
|
||||||
echo "PUBLISHING ${MOATS} : $RNAME"
|
|
||||||
|
|
||||||
if [[ $XDG_SESSION_TYPE != 'x11' ]]; then
|
|
||||||
(
|
|
||||||
cat ${MY_PATH}/tmp/http.${MOATS} | nc -l -p 33102 -q 1 > /dev/null 2>&1 \
|
|
||||||
&& rm -f "${MY_PATH}/tmp/http.${MOATS}" \
|
|
||||||
&& rm -f "${ZFILE}" \
|
|
||||||
&& rm -Rf "${ZFILE%.*}" \
|
|
||||||
&& echo "G1BILLETS FILE CONSUMED"
|
|
||||||
) &
|
|
||||||
else
|
|
||||||
rm -f "${MY_PATH}/tmp/http.${MOATS}" \
|
|
||||||
&& rm -f "${ZFILE}" \
|
|
||||||
&& rm -Rf "${ZFILE%.*}" \
|
|
||||||
&& echo "G1BILLETS FILE CONSUMED"
|
|
||||||
fi
|
|
||||||
|
|
||||||
end=`date +%s`
|
|
||||||
dur=`expr $end - $start`
|
|
||||||
echo "G1BILLET GENERATION WAS $dur SECONDS"
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
## EMPTY YESTERDAY TMP FILES
|
|
||||||
find ${MY_PATH}/tmp -mtime +1 -exec rm -Rf '{}' \;
|
|
||||||
|
|
||||||
done
|
|
||||||
#####################################################################
|
|
||||||
## loop ###############################################################TITLE="${file%.*}"
|
|
||||||
#####################################################################
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
exit 0
|
|
||||||
|
|
309
MAKE_G1BILLET.sh
|
@ -12,276 +12,79 @@ ME="${0##*/}"
|
||||||
############################################################################################################################################################
|
############################################################################################################################################################
|
||||||
# ${MY_PATH}/G1BILLET_MAKE.sh "nu me ro test" "se cr et" 100 7sn9dKeCNEsHmqm1gMWNREke4YAWtNw8KG1YBSN8CmSh 97968583
|
# ${MY_PATH}/G1BILLET_MAKE.sh "nu me ro test" "se cr et" 100 7sn9dKeCNEsHmqm1gMWNREke4YAWtNw8KG1YBSN8CmSh 97968583
|
||||||
############################################################################
|
############################################################################
|
||||||
export PATH="$HOME/.local/bin:$PATH"
|
|
||||||
|
|
||||||
## SEND LOG TO ~/.zen/tmp/_12345.log
|
NUMERO="$1"
|
||||||
exec 2>&1 >> ~/.zen/G1BILLET/tmp/G1BILLETS.log
|
SECRET="$2"
|
||||||
|
|
||||||
## LOAD PERSONAL OR DEFAULT STYLES
|
|
||||||
[[ -d ${MY_PATH}/_images/_/ ]] \
|
|
||||||
&& IMAGES="_images" \
|
|
||||||
|| IMAGES="images"
|
|
||||||
|
|
||||||
echo "$ME ~~~~~~~~~~~~~~~ @@@@@@ -------"
|
|
||||||
SECRET1="$1"
|
|
||||||
echo SECRET1=${SECRET1}
|
|
||||||
SECRET2="$2"
|
|
||||||
echo SECRET2=${SECRET2}
|
|
||||||
MONTANT="$3"
|
MONTANT="$3"
|
||||||
echo MONTANT=${MONTANT}
|
|
||||||
NOTERIB="$4"
|
NOTERIB="$4"
|
||||||
echo NOTERIB=${NOTERIB}
|
|
||||||
UNIQID="$5"
|
UNIQID="$5"
|
||||||
echo UNIQID=${UNIQID}
|
|
||||||
STYLE="$6"
|
STYLE="$6"
|
||||||
echo STYLE=${STYLE}
|
|
||||||
ASTRONS="$7"
|
|
||||||
echo ASTRONS=${ASTRONS}
|
|
||||||
EMAIL="$8"
|
|
||||||
echo EMAIL=${EMAIL}
|
|
||||||
|
|
||||||
if [[ "${SECRET1}" == "" || "$SECRET2" == "" || "$MONTANT" == "" || "$NOTERIB" == "" || "$UNIQID" == "" ]]
|
if [[ "$NUMERO" == "" || "$SECRET" == "" || "$MONTANT" == "" || "$NOTERIB" == "" || "$UNIQID" == "" ]]
|
||||||
then
|
then
|
||||||
echo "ERROR MISSING PARAM"
|
exit 1
|
||||||
exit 1
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
TAB=(${SECRET1} ${SECRET2})
|
mkdir -p /tmp/g1billet/$UNIQID
|
||||||
FULLDICE=${#TAB[@]}
|
BILLETNAME=$(echo $NUMERO | sed 's/ /_/g')
|
||||||
|
|
||||||
mkdir -p ${MY_PATH}/tmp/g1billet/$UNIQID
|
# Add ${MY_PATH}/images/logo.png (250px)
|
||||||
BILLETNAME=$(echo ${SECRET1} | sed 's/ /_/g')
|
composite -compose Over -gravity SouthWest -geometry +50+50 -dissolve 70% "${MY_PATH}/images/logo${STYLE}.png" "${MY_PATH}/images/fond${STYLE}.jpg" "/tmp/${BILLETNAME}.jpg"
|
||||||
|
|
||||||
IMAGESSTYLE="${IMAGES}/${STYLE}"
|
# Prepare BILLET qrcode verification URL
|
||||||
[[ ! -d ${MY_PATH}/${IMAGESSTYLE} ]] && IMAGESSTYLE="${IMAGES}/xastro" ## DEFAULT : TOOD CREATE UPlanet Style
|
qrencode -s 5 -o "/tmp/g1billet/${UNIQID}/${BILLETNAME}.QR.png" "$NOTERIB"
|
||||||
|
|
||||||
# Prepare June logo color
|
# Add verification QRCode
|
||||||
|
composite -compose Over -gravity SouthEast -geometry +45+60 "/tmp/g1billet/${UNIQID}/${BILLETNAME}.QR.png" "/tmp/${BILLETNAME}.jpg" "/tmp/${BILLETNAME}.jpg"
|
||||||
|
|
||||||
|
# Change June logo color
|
||||||
case "$MONTANT" in
|
case "$MONTANT" in
|
||||||
1)
|
1)
|
||||||
convert "${MY_PATH}/${IMAGESSTYLE}/fond.jpg" -fuzz 20% -fill grey -opaque '#17b317' "${MY_PATH}/tmp/g1billet/${UNIQID}/fond.jpg"
|
convert "${MY_PATH}/images/g1${STYLE}.png" -fuzz 20% -fill grey -opaque '#e5912b' "/tmp/g1billet/${UNIQID}/g1.png"
|
||||||
;;
|
;;
|
||||||
2)
|
2)
|
||||||
convert "${MY_PATH}/${IMAGESSTYLE}/fond.jpg" -fuzz 20% -fill green -opaque '#17b317' "${MY_PATH}/tmp/g1billet/${UNIQID}/fond.jpg"
|
convert "${MY_PATH}/images/g1${STYLE}.png" -fuzz 20% -fill green -opaque '#e5912b' "/tmp/g1billet/${UNIQID}/g1.png"
|
||||||
;;
|
;;
|
||||||
5)
|
5)
|
||||||
convert "${MY_PATH}/${IMAGESSTYLE}/fond.jpg" -fuzz 20% -fill orange -opaque '#17b317' "${MY_PATH}/tmp/g1billet/${UNIQID}/fond.jpg"
|
convert "${MY_PATH}/images/g1${STYLE}.png" -fuzz 20% -fill orange -opaque '#e5912b' "/tmp/g1billet/${UNIQID}/g1.png"
|
||||||
;;
|
;;
|
||||||
10)
|
10)
|
||||||
convert "${MY_PATH}/${IMAGESSTYLE}/fond.jpg" -fuzz 20% -fill blue -opaque '#17b317' "${MY_PATH}/tmp/g1billet/${UNIQID}/fond.jpg"
|
convert "${MY_PATH}/images/g1${STYLE}.png" -fuzz 20% -fill blue -opaque '#e5912b' "/tmp/g1billet/${UNIQID}/g1.png"
|
||||||
;;
|
;;
|
||||||
20)
|
20)
|
||||||
convert "${MY_PATH}/${IMAGESSTYLE}/fond.jpg" -fuzz 20% -fill purple -opaque '#17b317' "${MY_PATH}/tmp/g1billet/${UNIQID}/fond.jpg"
|
convert "${MY_PATH}/images/g1${STYLE}.png" -fuzz 20% -fill purple -opaque '#e5912b' "/tmp/g1billet/${UNIQID}/g1.png"
|
||||||
;;
|
;;
|
||||||
50)
|
50)
|
||||||
convert "${MY_PATH}/${IMAGESSTYLE}/fond.jpg" -fuzz 20% -fill red -opaque '#17b317' "${MY_PATH}/tmp/g1billet/${UNIQID}/fond.jpg"
|
convert "${MY_PATH}/images/g1${STYLE}.png" -fuzz 20% -fill red -opaque '#e5912b' "/tmp/g1billet/${UNIQID}/g1.png"
|
||||||
;;
|
;;
|
||||||
100)
|
100)
|
||||||
convert "${MY_PATH}/${IMAGESSTYLE}/fond.jpg" -fuzz 20% -fill black -opaque '#17b317' "${MY_PATH}/tmp/g1billet/${UNIQID}/fond.jpg"
|
convert "${MY_PATH}/images/g1${STYLE}.png" -fuzz 20% -fill black -opaque '#e5912b' "/tmp/g1billet/${UNIQID}/g1.png"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
cp "${MY_PATH}/${IMAGESSTYLE}/fond.jpg" "${MY_PATH}/tmp/g1billet/${UNIQID}/fond.jpg"
|
cp "${MY_PATH}/images/g1${STYLE}.png" "/tmp/g1billet/${UNIQID}/g1.png"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
## UPPER RIGHT SIGN (g1.png)
|
# Add June LOGO to Billet
|
||||||
cp "${MY_PATH}/${IMAGESSTYLE}/g1.png" "${MY_PATH}/tmp/g1billet/${UNIQID}/g1.png"
|
composite -compose Over -gravity NorthEast -geometry +50+25 -dissolve 90% "/tmp/g1billet/${UNIQID}/g1.png" "/tmp/${BILLETNAME}.jpg" "/tmp/${BILLETNAME}.jpg"
|
||||||
|
|
||||||
## ♥Box :: ZENCARD or ASTROID
|
|
||||||
|
|
||||||
BOTTOM="$(date) :: ♥Box :: _G1BILLET_ :: $(hostname) ::"
|
|
||||||
XZUID="__________@__________"
|
|
||||||
|
|
||||||
## PGP @PASS QRCODE
|
|
||||||
## NOT G1BILLET v1 : Create EXTRA PGP QR
|
|
||||||
if [[ "${STYLE:0:1}" != "_" && "${STYLE:0:1}" != "@" && ! "${STYLE}" =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$ ]]; then
|
|
||||||
|
|
||||||
USALT=$(echo "${SECRET1}" | jq -Rr @uri)
|
|
||||||
UPEPPER=$(echo "$SECRET2" | jq -Rr @uri)
|
|
||||||
## SECURED RANDOM salt : pepper GPG SEQUENCE
|
|
||||||
s=$(${MY_PATH}/diceware.sh 1 | xargs)
|
|
||||||
p=$(${MY_PATH}/diceware.sh 1 | xargs)
|
|
||||||
|
|
||||||
echo "(≖‿‿≖) PGP /?${s}=${USALT}&${p}=${UPEPPER} (PASS=$UNIQID)"
|
|
||||||
echo "/?${s}=${USALT}&${p}=${UPEPPER}" > ${MY_PATH}/tmp/topgp
|
|
||||||
cat ${MY_PATH}/tmp/topgp | gpg --symmetric --armor --batch --passphrase "$UNIQID" -o ${MY_PATH}/tmp/gpg.${BILLETNAME}.asc
|
|
||||||
rm ${MY_PATH}/tmp/topgp ## CLEANING CACHE
|
|
||||||
|
|
||||||
DISCO="$(cat ${MY_PATH}/tmp/gpg.${BILLETNAME}.asc | tr '-' '~' | tr '\n' '-' | tr '+' '_' | jq -Rr @uri )"
|
|
||||||
# [[ ${STYLE} == "UPlanet" ]] && DISCO="$(cat ${MY_PATH}/tmp/gpg.${BILLETNAME}.asc | tr '-' '&' | tr '\n' '-' | tr '+' '_' | jq -Rr @uri )" ## & ẑencard = (email/8digit)+4digit ## CALLED FROM VISA.new
|
|
||||||
|
|
||||||
echo "$DISCO"
|
|
||||||
|
|
||||||
## Put astrologo_nb in QRCode
|
|
||||||
cp ${MY_PATH}/${IMAGES}/astrologo_nb.png ${MY_PATH}/tmp/fond.png
|
|
||||||
|
|
||||||
## MAKE amzqr WITH astro:// LINK
|
|
||||||
amzqr -d ${MY_PATH}/tmp \
|
|
||||||
-l H \
|
|
||||||
-p ${MY_PATH}/tmp/fond.png \
|
|
||||||
"$DISCO" \
|
|
||||||
|| qrencode -s 6 -o "${MY_PATH}/tmp/fond_qrcode.png" "$DISCO"
|
|
||||||
|
|
||||||
## ADD PLAYER EMAIL
|
|
||||||
convert -gravity southeast -pointsize 28 -fill black -draw "text 5,3 \"${EMAIL}\"" ${MY_PATH}/tmp/fond_qrcode.png ${MY_PATH}/tmp/g1billet/${UNIQID}/${BILLETNAME}.ZENCARD.png
|
|
||||||
convert ${MY_PATH}/tmp/g1billet/${UNIQID}/${BILLETNAME}.ZENCARD.png -resize 320 ${MY_PATH}/tmp/g1billet/${UNIQID}/320.png
|
|
||||||
|
|
||||||
rm ${MY_PATH}/tmp/gpg.${BILLETNAME}.asc
|
|
||||||
|
|
||||||
|
# xbian style (ASTROPORT/KODI)
|
||||||
|
if [[ "${STYLE}" == "xbian" ]]
|
||||||
|
then
|
||||||
|
# CREATE PSEUDO for Gchange.fr
|
||||||
|
XZUID=$(${MY_PATH}/diceware.sh 1 | xargs)${RANDOM:0:2}$(${MY_PATH}/diceware.sh 1 | xargs)
|
||||||
|
BOTTOM="ASTROPORT KODI --- https://gchange.fr ---"
|
||||||
|
else
|
||||||
|
XZUID="G1 BILLET"
|
||||||
|
BOTTOM="Porte Monnaie Libre!! Utilisez avec https://cesium.app"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
## TW moa net
|
|
||||||
TWIMG="moa_net.png"
|
|
||||||
|
|
||||||
# ZENCARD+@ linked to G1BIILET ipns
|
|
||||||
[[ "${STYLE:0:1}" == "@" ]] \
|
|
||||||
&& TWIMG="pirate_map.png"
|
|
||||||
|
|
||||||
## G1BILLET+ linked to .current PLAYER TW (patch for Linkedin Fred)
|
|
||||||
[[ "${STYLE:0:1}" == "_" ]] \
|
|
||||||
&& ASTRONS="" \
|
|
||||||
&& TWIMG="web_internet.png"
|
|
||||||
|
|
||||||
if [[ ${ASTRONS} != "" ]] ; then
|
|
||||||
ASTROLINK="${ASTRONS}"
|
|
||||||
else
|
|
||||||
ASTROLINK="https://opencollective.com/made-in-zen"
|
|
||||||
fi
|
|
||||||
|
|
||||||
amzqr "${ASTROLINK}" \
|
|
||||||
-l H -p "$MY_PATH/${IMAGES}/${TWIMG}" \
|
|
||||||
-c -n QRTWavatar.png \
|
|
||||||
-d ${MY_PATH}/tmp/g1billet/${UNIQID}/ \
|
|
||||||
|| qrencode -s 6 -o "${MY_PATH}/tmp/g1billet/${UNIQID}/QRTWavatar.png" "${ASTROLINK}"
|
|
||||||
|
|
||||||
convert ${MY_PATH}/tmp/g1billet/${UNIQID}/QRTWavatar.png -resize 280 ${MY_PATH}/tmp/g1billet/${UNIQID}/TW.${ASTRONS}.png
|
|
||||||
|
|
||||||
|
|
||||||
[[ "${EMAIL}" != "" ]] && XZUID="${EMAIL}"
|
|
||||||
|
|
||||||
## ♥Box :: G1BILLET+ :: ZENCARD :: G1(TW)
|
|
||||||
|
|
||||||
# GIBILLET dice > 3 => G1BILLET+
|
|
||||||
[[ "${STYLE:0:1}" == "_" ]] \
|
|
||||||
&& mv ${MY_PATH}/tmp/g1billet/${UNIQID}/TW.${ASTRONS}.png ${MY_PATH}/tmp/g1billet/${UNIQID}/LEFT.png \
|
|
||||||
&& BOTTOM="$(date) :: ♥Box :: ẐBILLET+ :: $(hostname) ::"
|
|
||||||
|
|
||||||
[[ "${STYLE:0:1}" != "_" ]] \
|
|
||||||
&& mv ${MY_PATH}/tmp/g1billet/${UNIQID}/320.png ${MY_PATH}/tmp/g1billet/${UNIQID}/LEFT.png \
|
|
||||||
&& BOTTOM="$(date) :: ♥Box :: ZENCARD :: $(hostname) ::"
|
|
||||||
|
|
||||||
[[ "${STYLE:0:1}" == "x" ]] \
|
|
||||||
&& mv ${MY_PATH}/tmp/g1billet/${UNIQID}/TW.${ASTRONS}.png ${MY_PATH}/tmp/g1billet/${UNIQID}/CENTER.png \
|
|
||||||
&& BOTTOM="$(date) :: ♥Box :: ZENCARD+TW :: $(hostname) ::"
|
|
||||||
|
|
||||||
[[ "${STYLE}" == "UPlanet" ]] \
|
|
||||||
&& mv ${MY_PATH}/tmp/g1billet/${UNIQID}/TW.${ASTRONS}.png ${MY_PATH}/tmp/g1billet/${UNIQID}/CENTER.png \
|
|
||||||
&& BOTTOM="$(date) :: ♥UPLANET :: MADE-IN-ZEN :: $(hostname) ::"
|
|
||||||
|
|
||||||
if [[ "${STYLE:0:1}" == "@" || "${STYLE}" =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$ ]] ; then
|
|
||||||
#~ ########################## G1Voeu _ G1BILLET linking ##
|
|
||||||
## Astroport.ONE LINKING :: STYLE=EMAIL :: ZENCARD+@
|
|
||||||
# CREATE @PASS (G1G1BILLET+ G1Voeu derivated keys)
|
|
||||||
|
|
||||||
MOATS=$(date -u +"%Y%m%d%H%M%S%4N")
|
|
||||||
SRCMAIL=$(cat ~/.zen/game/players/.current/.player 2>/dev/null)
|
|
||||||
G1PUB=$(cat ~/.zen/game/players/.current/.g1pub 2>/dev/null)
|
|
||||||
|
|
||||||
#~ ## GET current PLAYER G1PUB
|
|
||||||
[[ -d ~/.zen/game/players/${STYLE} ]] \
|
|
||||||
&& SRCMAIL=${STYLE} && G1PUB=$(cat ~/.zen/game/players/${STYLE}/.g1pub 2>/dev/null)
|
|
||||||
|
|
||||||
BILLETFULLNAME=$(echo "${SRCMAIL} ${SECRET1} ${SECRET2}" | sed 's/ /_/g') # em@ai.l_dice_words
|
|
||||||
|
|
||||||
#### VOEUX.print.sh G1BILLET+
|
|
||||||
echo ~/.zen/Astroport.ONE/tools/VOEUX.print.sh "${BILLETFULLNAME}" "G1BILLET+" "${MOATS}" "${G1PUB}"
|
|
||||||
NEWIMAGIC=$(~/.zen/Astroport.ONE/tools/VOEUX.print.sh "${BILLETFULLNAME}" "G1BILLET+" "${MOATS}" "${G1PUB}" | tail -n 1)
|
|
||||||
convert ~/.zen/tmp/${MOATS}/START.png -resize 300 ${MY_PATH}/tmp/g1billet/${UNIQID}/LEFT.png
|
|
||||||
|
|
||||||
#~ ## REPLACE fond.jpg WITH moa.jpg from TW "Dession de PLAYER"
|
|
||||||
[[ -s ~/.zen/game/players/${SRCMAIL}/moa.jpg ]] \
|
|
||||||
&& rm ${MY_PATH}/tmp/g1billet/${UNIQID}/fond.jpg \
|
|
||||||
&& convert ~/.zen/game/players/${SRCMAIL}/moa.jpg -resize 964x459 -background grey -gravity center -extent 964x459 ${MY_PATH}/tmp/g1billet/${UNIQID}/fond.jpg
|
|
||||||
|
|
||||||
mv ${MY_PATH}/tmp/g1billet/${UNIQID}/TW.${ASTRONS}.png ${MY_PATH}/tmp/g1billet/${UNIQID}/CENTER.png
|
|
||||||
|
|
||||||
BILLNS=$(ipfs key import ${NOTERIB} -f pem-pkcs8-cleartext ~/.zen/tmp/${MOATS}/G1BILLET+.EXTRA.ipfskey)
|
|
||||||
#SIGN & HIDE SECRETS
|
|
||||||
#~ NOTERIB="https://ipfs.asycn.io/ipns/$BILLNS"
|
|
||||||
XZUID=${SRCMAIL}
|
|
||||||
BOTTOM="$(date) :: ♥Box :: ZENCARD+@ :: $(hostname) ::"
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
# ADD ASTROID LINK
|
|
||||||
|
|
||||||
# OVERLAY LOGO over FOND (logo.png)
|
|
||||||
composite -compose Over -dissolve 70% \
|
|
||||||
"${MY_PATH}/${IMAGESSTYLE}/logo.png" \
|
|
||||||
"${MY_PATH}/tmp/g1billet/${UNIQID}/fond.jpg" \
|
|
||||||
"${MY_PATH}/tmp/${BILLETNAME}.jpg"
|
|
||||||
|
|
||||||
### TEXT OVERLAY
|
|
||||||
#~ -pointsize 22 -draw 'text 50,100 "'"Secret 1: ${SECRET1}"'"' \
|
|
||||||
#~ -pointsize 22 -fill black -draw 'text 50,130 "'"Secret 2: $SECRET2"'"' \
|
|
||||||
|
|
||||||
if [[ "${STYLE:0:1}" != "_" && "${STYLE:0:1}" != "x" && ${MONTANT} != "___" ]]; then
|
|
||||||
convert -font 'Liberation-Sans' \
|
convert -font 'Liberation-Sans' \
|
||||||
-pointsize 40 -fill black -draw 'text 70,50 "'"$XZUID"'"' \
|
-pointsize 120 -fill black -draw 'text 330,250 "'"$MONTANT DU"'"' \
|
||||||
-pointsize 150 -fill black -draw 'text 120,380 "'"$MONTANT"'"' \
|
-pointsize 40 -fill black -draw 'text 75,50 "'"$XZUID"'"' \
|
||||||
-pointsize 20 -fill black -draw 'text 340,22 "'"${NOTERIB}"'"' \
|
-pointsize 30 -draw 'text 50,100 "'"Identifiant: $NUMERO"'"' \
|
||||||
-pointsize 25 -fill black -draw 'text 50,440 "'"$BOTTOM"'"' \
|
-pointsize 22 -fill black -draw 'text 50,130 "'"Code Secret: $SECRET"'"' \
|
||||||
"${MY_PATH}/tmp/${BILLETNAME}.jpg" "${MY_PATH}/tmp/g1billet/${UNIQID}/${BILLETNAME}.BILLET.jpg"
|
-pointsize 25 -fill black -draw 'text 150,440 "'"$BOTTOM"'"' \
|
||||||
else
|
"/tmp/${BILLETNAME}.jpg" "/tmp/g1billet/${UNIQID}/${BILLETNAME}.BILLET.jpg"
|
||||||
convert -font 'Liberation-Sans' \
|
|
||||||
-pointsize 35 -fill black -draw 'text 50,56 "'"$XZUID"'"' \
|
|
||||||
-pointsize 22 -fill black -draw 'text 300,26 "'"${NOTERIB}"'"' \
|
|
||||||
-pointsize 22 -fill black -draw 'text 50,85 "'"(Secret 1) ${SECRET1}"'"' \
|
|
||||||
-pointsize 22 -fill black -draw 'text 50,105 "'"(Secret 2) $SECRET2"'"' \
|
|
||||||
-pointsize 25 -fill grey -draw 'text 50,440 "'"$BOTTOM"'"' \
|
|
||||||
"${MY_PATH}/tmp/${BILLETNAME}.jpg" "${MY_PATH}/tmp/g1billet/${UNIQID}/${BILLETNAME}.BILLET.jpg"
|
|
||||||
fi
|
|
||||||
|
|
||||||
rm -f ${MY_PATH}/tmp/${BILLETNAME}.jpg
|
|
||||||
|
|
||||||
## ADD SouthWEST
|
|
||||||
[[ -s "${MY_PATH}/tmp/g1billet/${UNIQID}/LEFT.png" ]] && \
|
|
||||||
composite -compose Over -gravity SouthWest -geometry +30+30 \
|
|
||||||
"${MY_PATH}/tmp/g1billet/${UNIQID}/LEFT.png" \
|
|
||||||
"${MY_PATH}/tmp/g1billet/${UNIQID}/${BILLETNAME}.BILLET.jpg" \
|
|
||||||
"${MY_PATH}/tmp/g1billet/${UNIQID}/${BILLETNAME}.BILLET.jpg"
|
|
||||||
|
|
||||||
## ADD CENTER QRCODE
|
|
||||||
[[ -s "${MY_PATH}/tmp/g1billet/${UNIQID}/CENTER.png" ]] && \
|
|
||||||
composite -compose Over -gravity Center -geometry +30+40 \
|
|
||||||
"${MY_PATH}/tmp/g1billet/${UNIQID}/CENTER.png" \
|
|
||||||
"${MY_PATH}/tmp/g1billet/${UNIQID}/${BILLETNAME}.BILLET.jpg" \
|
|
||||||
"${MY_PATH}/tmp/g1billet/${UNIQID}/${BILLETNAME}.BILLET.jpg"
|
|
||||||
|
|
||||||
# G1PUB QR CODE RIGHT
|
|
||||||
[[ -s ${HOME}/.zen/Astroport.ONE/images/zenticket.png ]] \
|
|
||||||
&& amzqr "${NOTERIB}" -l H -p "${HOME}/.zen/Astroport.ONE/images/zenticket.png" -c -n QR.png -d ${MY_PATH}/tmp/g1billet/${UNIQID}/ \
|
|
||||||
&& convert ${MY_PATH}/tmp/g1billet/${UNIQID}/QR.png -resize 250 ${MY_PATH}/tmp/g1billet/${UNIQID}/${BILLETNAME}.QR.png \
|
|
||||||
&& rm ${MY_PATH}/tmp/g1billet/${UNIQID}/QR.png \
|
|
||||||
|| qrencode -s 6 -o "${MY_PATH}/tmp/g1billet/${UNIQID}/${BILLETNAME}.QR.png" "$NOTERIB"
|
|
||||||
|
|
||||||
# AJOUT DU G1PUB QRCODE A DROITE DU BILLET
|
|
||||||
composite -compose Over -gravity SouthEast -geometry +35+50 \
|
|
||||||
"${MY_PATH}/tmp/g1billet/${UNIQID}/${BILLETNAME}.QR.png" \
|
|
||||||
"${MY_PATH}/tmp/g1billet/${UNIQID}/${BILLETNAME}.BILLET.jpg" \
|
|
||||||
"${MY_PATH}/tmp/g1billet/${UNIQID}/${BILLETNAME}.BILLET.jpg"
|
|
||||||
|
|
||||||
# Add g1.png SIGLE
|
|
||||||
[[ "${STYLE:0:1}" != "@" && ! "${STYLE}" =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$ ]] && \
|
|
||||||
composite -compose Over -dissolve 90% \
|
|
||||||
"${MY_PATH}/tmp/g1billet/${UNIQID}/g1.png" \
|
|
||||||
"${MY_PATH}/tmp/g1billet/${UNIQID}/${BILLETNAME}.BILLET.jpg" \
|
|
||||||
"${MY_PATH}/tmp/g1billet/${UNIQID}/${BILLETNAME}.BILLET.jpg"
|
|
||||||
|
|
||||||
echo "$ME ~~~~~~~~~~~~~~~ @@@@@@ -------"
|
|
||||||
|
|
||||||
## BILLET READY in ${MY_PATH}/tmp/g1billet/${UNIQID}/${BILLETNAME}.BILLET.jpg
|
|
||||||
## NOT TO BE IN FINAL PDF (getting all jpg)
|
|
||||||
rm "${MY_PATH}/tmp/g1billet/${UNIQID}/fond.jpg"
|
|
||||||
|
|
||||||
exit 0
|
|
||||||
|
|
||||||
|
rm -f /tmp/${BILLETNAME}.jpg
|
||||||
|
|
224
README.md
|
@ -1,238 +1,82 @@
|
||||||
# G1BILLET
|
# G1BILLET
|
||||||
|
|
||||||
## Présentation
|
## Présentation
|
||||||
Ce code est un générateur de G1BILLETS qui utilise duniter.py keygen imagemagik amzqr
|
Ce code est un générateur de G1BILLETS
|
||||||
|
|
||||||
Il lance la fabrication de "G1 Portefeuilles" vides à remplir soi-même !
|
Il lance la fabrication de six "G1 Portefeuilles" vides à remplir soi-même !
|
||||||
Les G1Billets sont assemblés dans un fichier PDF pour les imprimer facilement sur une imprimante A4 et vous en servir comme chéquier.
|
Les G1Billets sont assemblés dans un fichier PDF pour les imprimer facilement sur une imprimante A4
|
||||||
|
|
||||||
Avant de vous en servir, utilisez Cesium pour flasher le QR Code et effectuer le virement correspondant à son montant sur chaque portefeuille.
|
Avant de vous en servir, utilisez Cesium pour flasher le QR Code et effectuer le virement correspondant à son montant sur chaque portefeuille.
|
||||||
Ensuite, offrez ces G1Billets à qui vous voulez.
|
Ensuite, offrez ces G1 Billets à qui vous voulez.
|
||||||
|
|
||||||
|
Son détenteur peut alors utiliser l'identifiant/mot de passe pour accéder au portefeuille correspondant.
|
||||||
|
|
||||||
Chaque billet est composé des images ```fond.jpg g1.png logo.png``` (à modifier ou remplacer par les votres) y sont ensuite ajouté différents signes et qrcodes.
|
* [DISCUSSION/FAQ/DETAILS](https://forum.monnaie-libre.fr/t/nouveau-g1-billets/14529?u=qoop)
|
||||||
|
* [DEMO EN VIDEO](./G1BILLETS.mp4)
|
||||||
En utilisant le style "xbian" vous activez le mode "ZenCard".
|
|
||||||
Un G1BILLET sécurisé qui fonctionne sur les [♥Box Ğ1Station](https://pad.p2p.legal/s/Astroport.ONE).
|
|
||||||
|
|
||||||
|
|
||||||
Son détenteur peut alors utiliser l'identifiant/mot de passe pour contrôler la clef du portefeuille correspondant.
|
|
||||||
|
|
||||||
* [FIL DE DISCUSSION SUR LE FORUM MONNAIE LIBRE](https://forum.monnaie-libre.fr/t/nouveau-g1-billets/14529?u=qoop)
|
|
||||||
* [VIDEO ZenCard TEASER](https://tube.p2p.legal/w/oBufWkzT3whWk3GabX3GAD)
|
|
||||||
|
|
||||||
> :warning: **Pour utiliser ZenCard : Installez [Astroport.ONE](https://git.p2p.legal/STI/Astroport.ONE).**
|
|
||||||
|
|
||||||
|
|
||||||
## Utilisation
|
## Utilisation
|
||||||
|
Pour une utilisation en ligne de commande, adaptez ces quelques lignes
|
||||||
En ligne de commande, adaptez ces lignes à votre style ;)
|
|
||||||
|
|
||||||
```
|
```
|
||||||
montant=0 # Valeur faciale à indiquer sur le billet (0 : indéfini)
|
Montant=5 # Valeur faciale à indiquer sur le billet
|
||||||
style="_" # Style du G1BILLET
|
NomFichier="nom_unique_du_pdf" # Correspond au nom du fichier créé dans /tmp/g1billet/
|
||||||
secu=7 # Nombre de mots "diceware" (corrélé à la complexité du PASS)
|
./G1BILLETS.sh "$Montant" "$NomFichier"
|
||||||
./G1BILLETS.sh "$montant" "$style" "$secu"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Personnalisez vos G1Billets, en modifiant les images dans ```images/$style``` (copiez-collez celles d'autres styles pour commencer le votre)
|
Pour personnaliser vos G1Billets, modifiez les images dans le répertoire du même nom (en conservant les dimensions)
|
||||||
|
La fabrication de la planche de G1Billets depuis un site web est possible en mettant le code dans un répertoire servi par un serveur web qui gère PHP...
|
||||||
|
|
||||||
* PLANCHE de 6 : http://g1billet.localhost:33101
|
## Installation
|
||||||
* G1TICKET de 10 : http://g1billet.localhost:33101/?montant=10&style=ticket
|
|
||||||
* ZenCard "avec dedicace" : http://g1billet.localhost:33101/?montant=0&style=votre@email.com
|
|
||||||
|
|
||||||
## Pré-requis Installation
|
Pour Linux le seul système d'opération qui respecte votre liberté
|
||||||
|
Ma recommandation: [Linux Mint](https://www.linuxmint.com/) ou [TwisterOS](https://twisteros.com/)
|
||||||
Pour Linux DEBIAN, Ubuntu, recommandé: [Linux Mint](https://www.linuxmint.com/)
|
|
||||||
|
|
||||||
```
|
```
|
||||||
# Installer git
|
# Installer git
|
||||||
sudo apt install git
|
sudo apt install git
|
||||||
```
|
```
|
||||||
|
|
||||||
# INSTALLATION (**for Linux (systemd) only**)
|
|
||||||
|
|
||||||
> :warning: **Vous souhaitez utiliser ZenCard? Installez [Astroport.ONE](https://git.p2p.legal/STI/Astroport.ONE).**
|
|
||||||
|
|
||||||
Utiliser le mode G1BILLET (seulement).
|
|
||||||
|
|
||||||
```
|
```
|
||||||
# Création et clonage du code dans ""~/.zen"
|
# Cloner le code de G1BILLET
|
||||||
mkdir -p ~/.zen
|
mkdir -p $HOME/bin/
|
||||||
cd ~/.zen
|
cd $HOME/bin/
|
||||||
git clone https://git.p2p.legal/qo-op/G1BILLET.git
|
git clone https://git.p2p.legal/qo-op/G1BILLET.git
|
||||||
cd G1BILLET
|
cd G1BILLET
|
||||||
|
|
||||||
# Installation
|
|
||||||
./install.sh
|
|
||||||
|
|
||||||
# Activation systemd
|
|
||||||
./setup_systemd.sh
|
|
||||||
|
|
||||||
## Ajouter raccourci sur votre Bureau
|
|
||||||
~/.zen/G1BILLET/add_desktop_shortcut.sh
|
|
||||||
|
|
||||||
## Ouvrir "Interface Web"
|
|
||||||
xdg-open http://localhost:33101/
|
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
Ajoutez les dépendances nécessaire
|
||||||
|
|
||||||
# CA NE FONCTIONNE PAS ?
|
|
||||||
|
|
||||||
Faites ces TESTS.
|
|
||||||
|
|
||||||
## Service is running ?
|
|
||||||
```
|
|
||||||
sudo systemctl status g1billet
|
|
||||||
|
|
||||||
● g1billet.service - G1BILLET API
|
|
||||||
Loaded: loaded (/etc/systemd/system/g1billet.service; enabled; vendor preset: enabled)
|
|
||||||
Active: active (running) since Thu 2023-04-20 21:11:39 CEST; 46min ago
|
|
||||||
Main PID: 3250895 (G1BILLETS.sh)
|
|
||||||
Tasks: 3 (limit: 18381)
|
|
||||||
Memory: 9.4M
|
|
||||||
CGroup: /system.slice/g1billet.service
|
|
||||||
├─3250895 /bin/bash /home/fred/workspace/G1BILLET/G1BILLETS.sh daemon
|
|
||||||
├─3253436 /bin/bash /home/fred/workspace/G1BILLET/G1BILLETS.sh daemon
|
|
||||||
└─3253438 nc -l -p 33101 -q 1
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## Crypto is working ?
|
|
||||||
```
|
|
||||||
./keygen 'toto' 'toto'
|
|
||||||
EA7Dsw39ShZg4SpURsrgMaMqrweJPUFPYHwZA8e92e3D
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
sudo apt install python3 python3-pip imagemagick qrencode ttf-mscorefonts-installer
|
||||||
## Graphics are OK ?
|
sudo pip3 install duniterpy
|
||||||
```
|
|
||||||
## CHANGE VARIABLES TO TEST YOUR STYLE ;)
|
|
||||||
SALT=toto; PEPPER=toto;
|
|
||||||
SECRET=toto; MONTANT=___;
|
|
||||||
BILLETPUBKEY=EA7Dsw39ShZg4SpURsrgMaMqrweJPUFPYHwZA8e92e3D;
|
|
||||||
UNIQID=toto; STYLE=xastro
|
|
||||||
ASTRONAUTENS=k51qzi5uqu5dl1zsbaala0bi26zpl5cfi7mogjwl9cg76d8awfc1d0iv738kak
|
|
||||||
EMAIL=toto@yopmail.com
|
|
||||||
|
|
||||||
BILLETNAME=$(echo $SALT | sed 's/ /_/g')
|
|
||||||
|
|
||||||
./MAKE_G1BILLET.sh "${SALT}" "${SECRET}" "${MONTANT}" "${BILLETPUBKEY}" "${UNIQID}" "${STYLE}" "${ASTRONAUTENS}" "${EMAIL}"
|
|
||||||
|
|
||||||
xdg-open tmp/g1billet/$UNIQID/$BILLETNAME.BILLET.jpg
|
|
||||||
```
|
```
|
||||||
|
|
||||||
* NB: Si une erreur du type "not autorized" apparait,
|
NB: Si une erreur du type "not autorized" apparait, vous devez autoriser la création de pdf en editant /etc/ImageMagick-6/policy.xml pour commenter la ligne:
|
||||||
éditez /etc/ImageMagick-6/policy.xml pour commenter la ligne qui bloque la création de "PDF"
|
|
||||||
|
|
||||||
ou réglez le problème avec ce script :
|
|
||||||
|
|
||||||
```
|
```
|
||||||
echo "######### CORRECT IMAGEMAGICK PDF ############"
|
<!-- <policy domain="coder" rights="none" pattern="PDF" /> -->
|
||||||
if [[ $(cat /etc/ImageMagick-6/policy.xml | grep PDF) ]]; then
|
|
||||||
cat /etc/ImageMagick-6/policy.xml | grep -Ev PDF > /tmp/policy.xml
|
|
||||||
sudo cp /tmp/policy.xml /etc/ImageMagick-6/policy.xml
|
|
||||||
fi
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## LOG monitoring
|
## Support
|
||||||
|
|
||||||
```
|
En créant ces G1Billets, vous devenez tiers de confiance...
|
||||||
tail -f ~/.zen/G1BILLET/tmp/G1BILLETS.log
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# PERSONNALISATION GRAPHIQUE
|
|
||||||
|
|
||||||
Pour changer le fond, le logo et le sigle de votre G1BILLET
|
|
||||||
|
|
||||||
Créez un répertoire dont le nom commence par "_"
|
|
||||||
et recopiez les modèles par défaut
|
|
||||||
|
|
||||||
```
|
|
||||||
mkdir -p ~/.zen/G1BILLET/_images
|
|
||||||
cp -R ~/.zen/G1BILLET/images/* ~/.zen/G1BILLET/_images
|
|
||||||
|
|
||||||
# Redémarrer G1BILLET
|
|
||||||
sudo systemctl restart g1billet
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
![](https://ipfs.copylaradio.com/ipfs/QmbLcxZR8C84PiSsFDbunSDj7nVfFC6TE2B8SjYnhp6Xuo)
|
|
||||||
|
|
||||||
Utilisez GIMP pour modifier les images...
|
|
||||||
|
|
||||||
# Support : [dites nous ce qui ne fonctionne pas](/qo-op/G1BILLET/issues)
|
|
||||||
[et ce qui fonctionne](https://pad.p2p.legal/s/G1BILLET)
|
|
||||||
|
|
||||||
En opérant le service G1BILLET, vous devenez "tiers de confiance".
|
|
||||||
Vous définissez l'usage selon votre envie
|
|
||||||
|
|
||||||
> La planche que vous allez imprimer est un chéquier multifonction.
|
|
||||||
|
|
||||||
Pour lui assurer une convertibilité en Ğ1, vous devrez [les créditer en flashant leur QRCode avec Cesium](https://forum.monnaie-libre.fr/t/nouveau-g1-billets/14529/4?u=qoop).
|
|
||||||
|
|
||||||
Une planche contient 6 G1BILLETS qui comportent des codes d'accès à "une clef de chiffrement" donnant accès à [notre crypto zone](https://www.copylaradio.com/blog/blog-1/post/espace-et-planetes-numeriques-33). Ces billets indiquent l'emplacement, la clef publique, et la clef, privée (ou non), d'un coffre numérique s'y trouvant.
|
|
||||||
|
|
||||||
G1BILLET révolutionne le "BILLET" tel que nous le connaissons...
|
|
||||||
|
|
||||||
## Un "bon au porteur" de nouvelle génération
|
|
||||||
|
|
||||||
**1. Effacer le secret**
|
|
||||||
|
|
||||||
* Définitivement_
|
|
||||||
|
|
||||||
Dans le cas où plus personne ne connaît le secret, et ce qui est relié à ce G1BILLET est immuable (impossible à vider).
|
|
||||||
|
|
||||||
Sa valeur en G1 pourra augmenter mais celle du morceau de papier dépendra du contrôle du nombre de ses copies,
|
|
||||||
C'est la version qui se rapproche le plus de ce que nous connaissons comme "Billet de Banque".
|
|
||||||
Celui-ci devrait donc être détruit lorsque son émetteur le "récupère" en assurant la convertibilité promise.
|
|
||||||
|
|
||||||
Associé à des données multimédia, vous disposez d'un "Bon pour y accéder" que vous pouvez offrir.
|
|
||||||
Selon la nature de ces données, devenues immuables et associables à des défis, ils sont utilisables pour "monétiser l'accès aux données".
|
|
||||||
|
|
||||||
* Temporairement_
|
|
||||||
|
|
||||||
En cachant le secret sous une couche "case à gratter" par exemple, le G1BILLET peut passer de son statut "Billet de Banque" à celui de Cadeau à accepter.
|
|
||||||
Son contenu en G1 est alors récupérable par celui qui révèle le secret. A ce moment, l’œuvre et le portefeuille associée au G1BILLET appartiennent pleinement à son propriétaire.
|
|
||||||
|
|
||||||
> Garder une copie du secret ou pas.
|
|
||||||
> C'est ce qui conditionne le premier maillon de confiance.
|
|
||||||
|
|
||||||
**1. Laisser le secret**
|
|
||||||
|
|
||||||
Dans ce cas, le "bien numérique" rattaché à ce secret est sous le contrôle de celui qui utilise ce codes, donc le possède, ou en aura fait une copie.
|
|
||||||
Cela concerne une ressource commune et abondante pour un groupe à bon niveau de confiance relatif
|
|
||||||
|
|
||||||
Par exemple, on pourra s'en servir comme Kit découverte "Gchange/Cesium" à offrir à ses amis (avec de la monnaie dessus ou pas).
|
|
||||||
|
|
||||||
|
|
||||||
**Essayez!! Envoyez-nous vos expériences...**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
Réalisé et offert dans l'espoir que la(/les) monnaie(s) libre(s) deviennent réalité pour tous.
|
Réalisé et offert dans l'espoir que la(/les) monnaie(s) libre(s) deviennent réalité pour tous.
|
||||||
|
|
||||||
> Le saviez-vous ? Vous pouvez ouvrir un compte sur [GCHANGE](https://gchange.fr) avec les identifiants de votre G1BILLET/ZenCard.
|
IMPORTANT!! Invitez celles et ceux à qui vous offrez ces G1 Billets à ouvrir un compte sur [GCHANGE](https://gchange.fr) et à proposer leurs services, objets et créations.
|
||||||
Il s'agit également d'un portefeuille [Cesium](https://cesium.app).
|
|
||||||
|
|
||||||
> :warning: ATTENTION. N'utilisez pas ce compte pour devenir membre forgeron !
|
Merci pour vos encouragements et/ou vos dons
|
||||||
Ou bien créez un ZenCard de haute sécurité que vous n'utiliserez que sur Cesium dans ce cas précis.
|
* [JUNE](https://demo.cesium.app/#/app/wot/DsEx1pS33vzYZg4MroyBV9hCw98j1gtHEhwiZ5tK7ech/Fred)
|
||||||
|
* [UNL](https://opencollective.com/monnaie-libre)
|
||||||
|
* [PAYPAL](https://www.paypal.com/paypalme/QWANTIC)
|
||||||
|
|
||||||
Merci pour vos encouragements et vos dons en JUNE
|
Vous avez des questions? Contactez [Fred](mailto:support@qo-op.com)
|
||||||
|
|
||||||
* [Fred](https://demo.cesium.app/#/app/wot/DsEx1pS33vzYZg4MroyBV9hCw98j1gtHEhwiZ5tK7ech/Fred)
|
|
||||||
|
|
||||||
|
|
||||||
Des questions? Contactez [support@qo-op.com](mailto:support@qo-op.com)
|
Ce code écrit en bash est un recyclage simplifié de celui utilisé dans [g1sms](https://git.p2p.legal/axiom-team/G1sms)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# [OpenCollective](https://opencollective.com/monnaie-libre)
|
[G1SMS](https://g1sms.fr)
|
||||||
|
|
||||||
## On compte sur vous.
|
|
||||||
|
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
################################################################################
|
|
||||||
# Author: Fred (support@qo-op.com)
|
|
||||||
# Version: 0.1
|
|
||||||
# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/)
|
|
||||||
################################################################################
|
|
||||||
MY_PATH="`dirname \"$0\"`" # relative
|
|
||||||
MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized
|
|
||||||
ME="${0##*/}"
|
|
||||||
|
|
||||||
[[ -d ~/Bureau ]] && sed "s/_USER_/$USER/g" ${MY_PATH}/g1billet.desktop > ~/Bureau/g1billet.desktop && chmod +x ~/Bureau/g1billet.desktop
|
|
||||||
[[ -d ~/Desktop ]] && sed "s/_USER_/$USER/g" ${MY_PATH}/g1billet.desktop > ~/Desktop/g1billet.desktop && chmod +x ~/Desktop/g1billet.desktop
|
|
22
crypto.proto
|
@ -1,22 +0,0 @@
|
||||||
syntax = "proto2";
|
|
||||||
|
|
||||||
package crypto.pb;
|
|
||||||
|
|
||||||
option go_package = "github.com/libp2p/go-libp2p-core/crypto/pb";
|
|
||||||
|
|
||||||
enum KeyType {
|
|
||||||
RSA = 0;
|
|
||||||
Ed25519 = 1;
|
|
||||||
Secp256k1 = 2;
|
|
||||||
ECDSA = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
message PublicKey {
|
|
||||||
required KeyType Type = 1;
|
|
||||||
required bytes Data = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
message PrivateKey {
|
|
||||||
required KeyType Type = 1;
|
|
||||||
required bytes Data = 2;
|
|
||||||
}
|
|
162
crypto_pb2.py
|
@ -1,162 +0,0 @@
|
||||||
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
|
||||||
# source: crypto.proto
|
|
||||||
|
|
||||||
import sys
|
|
||||||
_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
|
|
||||||
from google.protobuf.internal import enum_type_wrapper
|
|
||||||
from google.protobuf import descriptor as _descriptor
|
|
||||||
from google.protobuf import message as _message
|
|
||||||
from google.protobuf import reflection as _reflection
|
|
||||||
from google.protobuf import symbol_database as _symbol_database
|
|
||||||
# @@protoc_insertion_point(imports)
|
|
||||||
|
|
||||||
_sym_db = _symbol_database.Default()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
DESCRIPTOR = _descriptor.FileDescriptor(
|
|
||||||
name='crypto.proto',
|
|
||||||
package='crypto.pb',
|
|
||||||
syntax='proto2',
|
|
||||||
serialized_options=_b('Z*github.com/libp2p/go-libp2p-core/crypto/pb'),
|
|
||||||
serialized_pb=_b('\n\x0c\x63rypto.proto\x12\tcrypto.pb\";\n\tPublicKey\x12 \n\x04Type\x18\x01 \x02(\x0e\x32\x12.crypto.pb.KeyType\x12\x0c\n\x04\x44\x61ta\x18\x02 \x02(\x0c\"<\n\nPrivateKey\x12 \n\x04Type\x18\x01 \x02(\x0e\x32\x12.crypto.pb.KeyType\x12\x0c\n\x04\x44\x61ta\x18\x02 \x02(\x0c*9\n\x07KeyType\x12\x07\n\x03RSA\x10\x00\x12\x0b\n\x07\x45\x64\x32\x35\x35\x31\x39\x10\x01\x12\r\n\tSecp256k1\x10\x02\x12\t\n\x05\x45\x43\x44SA\x10\x03\x42,Z*github.com/libp2p/go-libp2p-core/crypto/pb')
|
|
||||||
)
|
|
||||||
|
|
||||||
_KEYTYPE = _descriptor.EnumDescriptor(
|
|
||||||
name='KeyType',
|
|
||||||
full_name='crypto.pb.KeyType',
|
|
||||||
filename=None,
|
|
||||||
file=DESCRIPTOR,
|
|
||||||
values=[
|
|
||||||
_descriptor.EnumValueDescriptor(
|
|
||||||
name='RSA', index=0, number=0,
|
|
||||||
serialized_options=None,
|
|
||||||
type=None),
|
|
||||||
_descriptor.EnumValueDescriptor(
|
|
||||||
name='Ed25519', index=1, number=1,
|
|
||||||
serialized_options=None,
|
|
||||||
type=None),
|
|
||||||
_descriptor.EnumValueDescriptor(
|
|
||||||
name='Secp256k1', index=2, number=2,
|
|
||||||
serialized_options=None,
|
|
||||||
type=None),
|
|
||||||
_descriptor.EnumValueDescriptor(
|
|
||||||
name='ECDSA', index=3, number=3,
|
|
||||||
serialized_options=None,
|
|
||||||
type=None),
|
|
||||||
],
|
|
||||||
containing_type=None,
|
|
||||||
serialized_options=None,
|
|
||||||
serialized_start=150,
|
|
||||||
serialized_end=207,
|
|
||||||
)
|
|
||||||
_sym_db.RegisterEnumDescriptor(_KEYTYPE)
|
|
||||||
|
|
||||||
KeyType = enum_type_wrapper.EnumTypeWrapper(_KEYTYPE)
|
|
||||||
RSA = 0
|
|
||||||
Ed25519 = 1
|
|
||||||
Secp256k1 = 2
|
|
||||||
ECDSA = 3
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
_PUBLICKEY = _descriptor.Descriptor(
|
|
||||||
name='PublicKey',
|
|
||||||
full_name='crypto.pb.PublicKey',
|
|
||||||
filename=None,
|
|
||||||
file=DESCRIPTOR,
|
|
||||||
containing_type=None,
|
|
||||||
fields=[
|
|
||||||
_descriptor.FieldDescriptor(
|
|
||||||
name='Type', full_name='crypto.pb.PublicKey.Type', index=0,
|
|
||||||
number=1, type=14, cpp_type=8, label=2,
|
|
||||||
has_default_value=False, default_value=0,
|
|
||||||
message_type=None, enum_type=None, containing_type=None,
|
|
||||||
is_extension=False, extension_scope=None,
|
|
||||||
serialized_options=None, file=DESCRIPTOR),
|
|
||||||
_descriptor.FieldDescriptor(
|
|
||||||
name='Data', full_name='crypto.pb.PublicKey.Data', index=1,
|
|
||||||
number=2, type=12, cpp_type=9, label=2,
|
|
||||||
has_default_value=False, default_value=_b(""),
|
|
||||||
message_type=None, enum_type=None, containing_type=None,
|
|
||||||
is_extension=False, extension_scope=None,
|
|
||||||
serialized_options=None, file=DESCRIPTOR),
|
|
||||||
],
|
|
||||||
extensions=[
|
|
||||||
],
|
|
||||||
nested_types=[],
|
|
||||||
enum_types=[
|
|
||||||
],
|
|
||||||
serialized_options=None,
|
|
||||||
is_extendable=False,
|
|
||||||
syntax='proto2',
|
|
||||||
extension_ranges=[],
|
|
||||||
oneofs=[
|
|
||||||
],
|
|
||||||
serialized_start=27,
|
|
||||||
serialized_end=86,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
_PRIVATEKEY = _descriptor.Descriptor(
|
|
||||||
name='PrivateKey',
|
|
||||||
full_name='crypto.pb.PrivateKey',
|
|
||||||
filename=None,
|
|
||||||
file=DESCRIPTOR,
|
|
||||||
containing_type=None,
|
|
||||||
fields=[
|
|
||||||
_descriptor.FieldDescriptor(
|
|
||||||
name='Type', full_name='crypto.pb.PrivateKey.Type', index=0,
|
|
||||||
number=1, type=14, cpp_type=8, label=2,
|
|
||||||
has_default_value=False, default_value=0,
|
|
||||||
message_type=None, enum_type=None, containing_type=None,
|
|
||||||
is_extension=False, extension_scope=None,
|
|
||||||
serialized_options=None, file=DESCRIPTOR),
|
|
||||||
_descriptor.FieldDescriptor(
|
|
||||||
name='Data', full_name='crypto.pb.PrivateKey.Data', index=1,
|
|
||||||
number=2, type=12, cpp_type=9, label=2,
|
|
||||||
has_default_value=False, default_value=_b(""),
|
|
||||||
message_type=None, enum_type=None, containing_type=None,
|
|
||||||
is_extension=False, extension_scope=None,
|
|
||||||
serialized_options=None, file=DESCRIPTOR),
|
|
||||||
],
|
|
||||||
extensions=[
|
|
||||||
],
|
|
||||||
nested_types=[],
|
|
||||||
enum_types=[
|
|
||||||
],
|
|
||||||
serialized_options=None,
|
|
||||||
is_extendable=False,
|
|
||||||
syntax='proto2',
|
|
||||||
extension_ranges=[],
|
|
||||||
oneofs=[
|
|
||||||
],
|
|
||||||
serialized_start=88,
|
|
||||||
serialized_end=148,
|
|
||||||
)
|
|
||||||
|
|
||||||
_PUBLICKEY.fields_by_name['Type'].enum_type = _KEYTYPE
|
|
||||||
_PRIVATEKEY.fields_by_name['Type'].enum_type = _KEYTYPE
|
|
||||||
DESCRIPTOR.message_types_by_name['PublicKey'] = _PUBLICKEY
|
|
||||||
DESCRIPTOR.message_types_by_name['PrivateKey'] = _PRIVATEKEY
|
|
||||||
DESCRIPTOR.enum_types_by_name['KeyType'] = _KEYTYPE
|
|
||||||
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
|
|
||||||
|
|
||||||
PublicKey = _reflection.GeneratedProtocolMessageType('PublicKey', (_message.Message,), dict(
|
|
||||||
DESCRIPTOR = _PUBLICKEY,
|
|
||||||
__module__ = 'crypto_pb2'
|
|
||||||
# @@protoc_insertion_point(class_scope:crypto.pb.PublicKey)
|
|
||||||
))
|
|
||||||
_sym_db.RegisterMessage(PublicKey)
|
|
||||||
|
|
||||||
PrivateKey = _reflection.GeneratedProtocolMessageType('PrivateKey', (_message.Message,), dict(
|
|
||||||
DESCRIPTOR = _PRIVATEKEY,
|
|
||||||
__module__ = 'crypto_pb2'
|
|
||||||
# @@protoc_insertion_point(class_scope:crypto.pb.PrivateKey)
|
|
||||||
))
|
|
||||||
_sym_db.RegisterMessage(PrivateKey)
|
|
||||||
|
|
||||||
|
|
||||||
DESCRIPTOR._options = None
|
|
||||||
# @@protoc_insertion_point(module_scope)
|
|
|
@ -1,7 +0,0 @@
|
||||||
#!/usr/bin/env xdg-open
|
|
||||||
[Desktop Entry]
|
|
||||||
Name=G1BILLET
|
|
||||||
Exec=xdg-open http://localhost:33101
|
|
||||||
Icon=/home/_USER_/.zen/G1BILLET/g1logo.png
|
|
||||||
Type=Application
|
|
||||||
Categories=Utility
|
|
BIN
g1logo.png
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 147 KiB |
Before Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 97 KiB |
Before Width: | Height: | Size: 825 B |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 116 KiB |
BIN
images/_/g1.png
Before Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 87 KiB |
Before Width: | Height: | Size: 35 KiB |
After Width: | Height: | Size: 120 KiB |
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 104 KiB |
After Width: | Height: | Size: 147 KiB |
After Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 45 KiB |
After Width: | Height: | Size: 76 KiB |
After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 65 KiB |
Before Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 104 KiB |
After Width: | Height: | Size: 77 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 280 KiB |
Before Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 63 KiB |
Before Width: | Height: | Size: 161 KiB |
Before Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 180 KiB |
Before Width: | Height: | Size: 83 KiB |
Before Width: | Height: | Size: 147 KiB |
Before Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 104 KiB |
Before Width: | Height: | Size: 48 KiB |
23
index.php
|
@ -2,29 +2,22 @@
|
||||||
$mytime = new Datetime("now");
|
$mytime = new Datetime("now");
|
||||||
$timestamp = $mytime->format('U').rand();
|
$timestamp = $mytime->format('U').rand();
|
||||||
|
|
||||||
/// BROKEN PREFER DAEMON MODE
|
|
||||||
// CREATE 6 G1BILLETS in /tmp/g1billet/$timestamp
|
// CREATE 6 G1BILLETS in /tmp/g1billet/$timestamp
|
||||||
$page = shell_exec(dirname(__FILE__)."/G1BILLETS.sh '".$_REQUEST['montant']."' '".$timestamp."' '".$_REQUEST['style']."'");
|
$page = shell_exec(dirname(__FILE__)."/G1BILLETS.sh '".$_REQUEST['montant']."' '".$timestamp."' '".$_REQUEST['style']."'");
|
||||||
|
|
||||||
if ( $_REQUEST['style'] == 'ticket' || $_REQUEST['style'] == 'xbian' || $_REQUEST['style'] == 'astro' ) {
|
$attachment_location = "/tmp/g1billet/".$timestamp.".pdf";
|
||||||
$file_type = "jpg";
|
|
||||||
} else {
|
|
||||||
$file_type = "pdf";
|
|
||||||
}
|
|
||||||
$attachment_location = dirname(__FILE__)."/tmp/g1billet/".$timestamp.".".$file_type;
|
|
||||||
|
|
||||||
if (file_exists($attachment_location)) {
|
if (file_exists($attachment_location)) {
|
||||||
header($_SERVER["SERVER_PROTOCOL"] . " 200 OK");
|
header($_SERVER["SERVER_PROTOCOL"] . " 200 OK");
|
||||||
header("Cache-Control: public"); // needed for internet explorer
|
header("Cache-Control: public"); // needed for internet explorer
|
||||||
header("Content-Type: application/".$file_type);
|
header("Content-Type: application/pdf");
|
||||||
header("Content-Transfer-Encoding: Binary");
|
header("Content-Transfer-Encoding: Binary");
|
||||||
header("Content-Length:".filesize($attachment_location));
|
header("Content-Length:".filesize($attachment_location));
|
||||||
header("Content-Disposition: attachment; filename=".$timestamp.".".$file_type);
|
header("Content-Disposition: attachment; filename=".$timestamp.".pdf");
|
||||||
readfile($attachment_location);
|
readfile($attachment_location);
|
||||||
unlink(dirname(__FILE__)."/tmp/g1billet/".$timestamp.".".$file_type);
|
unlink("/tmp/g1billet/".$timestamp.".pdf");
|
||||||
die();
|
die();
|
||||||
} else {
|
} else {
|
||||||
die("Error: File not found.".$attachment_location);
|
die("Error: File not found.");
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
|
||||||
|
|
35
install.sh
|
@ -1,35 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
################################################################################
|
|
||||||
# Author: Fred (support@qo-op.com)
|
|
||||||
# Version: 0.1
|
|
||||||
# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/)
|
|
||||||
################################################################################
|
|
||||||
MY_PATH="`dirname \"$0\"`" # relative
|
|
||||||
MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized
|
|
||||||
ME="${0##*/}"
|
|
||||||
|
|
||||||
echo "#############################################"
|
|
||||||
echo ">>>>>>>>>>> INSTALL CRYPTO AND IMAGING TOOLS "
|
|
||||||
echo "#############################################"
|
|
||||||
sudo apt-get update
|
|
||||||
|
|
||||||
for i in gpg python3 python3-pip imagemagick qrencode ttf-mscorefonts-installer netcat-traditional python3-gpg; do
|
|
||||||
if [ $(dpkg-query -W -f='${Status}' $i 2>/dev/null | grep -c "ok installed") -eq 0 ]; then
|
|
||||||
echo ">>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Installation $i <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
|
|
||||||
sudo apt install -y $i
|
|
||||||
[[ $? != 0 ]] && echo "INSTALL $i FAILED." && echo "INSTALL $i FAILED." && continue
|
|
||||||
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
for i in pip setuptools wheel cryptography==3.4.8 Ed25519 base58 google duniterpy pynacl pgpy pynentry SecureBytes amzqr; do
|
|
||||||
echo ">>> Installation $i <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
|
|
||||||
sudo python3 -m pip install -U $i
|
|
||||||
[[ $? != 0 ]] && echo "python3 -m pip install -U $i FAILED." && continue
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "# Correction des droits export PDF imagemagick"
|
|
||||||
if [[ $(cat /etc/ImageMagick-6/policy.xml | grep PDF) ]]; then
|
|
||||||
cat /etc/ImageMagick-6/policy.xml | grep -Ev PDF > /tmp/policy.xml
|
|
||||||
sudo cp /tmp/policy.xml /etc/ImageMagick-6/policy.xml
|
|
||||||
fi
|
|
896
keygen
|
@ -1,896 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
# link: https://git.p2p.legal/aya/dpgpid/
|
|
||||||
# desc: generate ed25519 keys for duniter and ipfs from gpg
|
|
||||||
|
|
||||||
# Copyleft 2022 Yann Autissier <aya@asycn.io>
|
|
||||||
# all crypto science belongs to Pascal Engélibert <tuxmain@zettascript.org>
|
|
||||||
# coming from files available at https://git.p2p.legal/qo-op/Astroport.ONE/tools
|
|
||||||
# gpgme stuff has been provided by Ben McGinnes
|
|
||||||
# and comes from http://files.au.adversary.org/crypto/gpgme-python-howto.html
|
|
||||||
# gpg key extraction is taken from work of Simon Vareille available at
|
|
||||||
# https://gist.github.com/SimonVareille/fda49baf5f3e15b5c88e25560aeb2822
|
|
||||||
|
|
||||||
# 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 <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
import argparse
|
|
||||||
import base58
|
|
||||||
import base64
|
|
||||||
import configparser
|
|
||||||
from cryptography.hazmat.primitives.asymmetric import ed25519
|
|
||||||
from cryptography.hazmat.primitives import serialization
|
|
||||||
import duniterpy.key
|
|
||||||
import gpg
|
|
||||||
from jwcrypto import jwk
|
|
||||||
import logging as log
|
|
||||||
import nacl.bindings
|
|
||||||
import nacl.encoding
|
|
||||||
import pgpy
|
|
||||||
import pynentry
|
|
||||||
from SecureBytes import clearmem
|
|
||||||
import os
|
|
||||||
import re
|
|
||||||
import struct
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
import warnings
|
|
||||||
|
|
||||||
__version__='0.0.5'
|
|
||||||
|
|
||||||
class keygen:
|
|
||||||
def __init__(self):
|
|
||||||
self.parser = argparse.ArgumentParser(description="""
|
|
||||||
Generate ed25519 keys for duniter and ipfs from gpg.
|
|
||||||
It converts a gpg key, a duniter username/password, or any ed25519 key to
|
|
||||||
a duniter wallet or an IPFS key.""")
|
|
||||||
self.parser.add_argument(
|
|
||||||
"-d",
|
|
||||||
"--debug",
|
|
||||||
action="store_true",
|
|
||||||
help="show debug informations (WARNING: including SECRET KEY)",
|
|
||||||
)
|
|
||||||
self.parser.add_argument(
|
|
||||||
"-f",
|
|
||||||
"--format",
|
|
||||||
choices=['ewif', 'jwk', 'nacl','pb2','pem','pubsec','seed','wif'],
|
|
||||||
default=None,
|
|
||||||
dest="format",
|
|
||||||
help="output file format, default: pem (pkcs8)",
|
|
||||||
)
|
|
||||||
self.parser.add_argument(
|
|
||||||
"-g",
|
|
||||||
"--gpg",
|
|
||||||
action="store_true",
|
|
||||||
help="use gpg key with uid matched by username",
|
|
||||||
)
|
|
||||||
self.parser.add_argument(
|
|
||||||
"-i",
|
|
||||||
"--input",
|
|
||||||
dest="input",
|
|
||||||
help="read ed25519 key from file FILE, autodetect format: {credentials,ewif,jwk,nacl,mnemonic,pb2,pubsec,seed,wif}",
|
|
||||||
metavar='FILE',
|
|
||||||
)
|
|
||||||
self.parser.add_argument(
|
|
||||||
"-k",
|
|
||||||
"--keys",
|
|
||||||
action="store_true",
|
|
||||||
help="show public and secret keys",
|
|
||||||
)
|
|
||||||
self.parser.add_argument(
|
|
||||||
"-m",
|
|
||||||
"--mnemonic",
|
|
||||||
action="store_true",
|
|
||||||
help="use username as a DUBP mnemonic passphrase",
|
|
||||||
)
|
|
||||||
self.parser.add_argument(
|
|
||||||
"-o",
|
|
||||||
"--output",
|
|
||||||
dest="output",
|
|
||||||
default=None,
|
|
||||||
help="write ed25519 key to file FILE",
|
|
||||||
metavar='FILE',
|
|
||||||
)
|
|
||||||
self.parser.add_argument(
|
|
||||||
"-p",
|
|
||||||
"--prefix",
|
|
||||||
action="store_true",
|
|
||||||
help="prefix output text with key type",
|
|
||||||
)
|
|
||||||
self.parser.add_argument(
|
|
||||||
"-q",
|
|
||||||
"--quiet",
|
|
||||||
action="store_true",
|
|
||||||
help="show only errors",
|
|
||||||
)
|
|
||||||
self.parser.add_argument(
|
|
||||||
"-s",
|
|
||||||
"--secret",
|
|
||||||
action="store_true",
|
|
||||||
help="show only secret key",
|
|
||||||
)
|
|
||||||
self.parser.add_argument(
|
|
||||||
"-t",
|
|
||||||
"--type",
|
|
||||||
choices=['b58mh','b64mh','base58','base64','duniter','ipfs','jwk'],
|
|
||||||
default="base58",
|
|
||||||
dest="type",
|
|
||||||
help="output text format, default: base58",
|
|
||||||
)
|
|
||||||
self.parser.add_argument(
|
|
||||||
"-v",
|
|
||||||
"--verbose",
|
|
||||||
action="store_true",
|
|
||||||
help="show more informations",
|
|
||||||
)
|
|
||||||
self.parser.add_argument(
|
|
||||||
"--version",
|
|
||||||
action="store_true",
|
|
||||||
help="show version and exit",
|
|
||||||
)
|
|
||||||
self.parser.add_argument(
|
|
||||||
'username',
|
|
||||||
nargs="?",
|
|
||||||
)
|
|
||||||
self.parser.add_argument(
|
|
||||||
'password',
|
|
||||||
nargs="?",
|
|
||||||
)
|
|
||||||
|
|
||||||
def _check_args(self, args):
|
|
||||||
log.debug("keygen._check_args(%s)" % args)
|
|
||||||
if self.input is None and self.username is None:
|
|
||||||
self.parser.error('keygen requires an input file or a username')
|
|
||||||
|
|
||||||
def _cleanup(self):
|
|
||||||
log.debug("keygen._cleanup()")
|
|
||||||
if hasattr(self, 'duniterpy'):
|
|
||||||
if hasattr(self.duniterpy, 'seed') and self.duniterpy.seed:
|
|
||||||
clearmem(self.duniterpy.seed)
|
|
||||||
log.debug("cleared: keygen.duniterpy.seed")
|
|
||||||
if hasattr(self.duniterpy, 'sk') and self.duniterpy.sk:
|
|
||||||
clearmem(self.duniterpy.sk)
|
|
||||||
log.debug("cleared: keygen.duniterpy.sk")
|
|
||||||
if hasattr(self, 'ed25519_secret_base58') and self.ed25519_secret_base58:
|
|
||||||
clearmem(self.ed25519_secret_base58)
|
|
||||||
log.debug("cleared: keygen.ed25519_secret_base58")
|
|
||||||
if hasattr(self, 'ed25519_secret_base64') and self.ed25519_secret_base64:
|
|
||||||
clearmem(self.ed25519_secret_base64)
|
|
||||||
log.debug("cleared: keygen.ed25519_secret_base64")
|
|
||||||
if hasattr(self, 'ed25519_secret_bytes') and self.ed25519_secret_bytes:
|
|
||||||
clearmem(self.ed25519_secret_bytes)
|
|
||||||
log.debug("cleared: keygen.ed25519_secret_bytes")
|
|
||||||
if hasattr(self, 'ed25519_secret_pem_pkcs8') and self.ed25519_secret_pem_pkcs8:
|
|
||||||
clearmem(self.ed25519_secret_pem_pkcs8)
|
|
||||||
log.debug("cleared: keygen.ed25515_secret_pem_pkcs8")
|
|
||||||
if hasattr(self, 'ed25519_secret_protobuf') and self.ed25519_secret_protobuf:
|
|
||||||
clearmem(self.ed25519_secret_protobuf)
|
|
||||||
log.debug("cleared: keygen.ed25515_secret_protobuf")
|
|
||||||
if hasattr(self, 'ed25519_seed_bytes') and self.ed25519_seed_bytes:
|
|
||||||
clearmem(self.ed25519_seed_bytes)
|
|
||||||
log.debug("cleared: keygen.ed25519_seed_bytes")
|
|
||||||
if hasattr(self, 'ipfs_privkey') and self.ipfs_privkey:
|
|
||||||
clearmem(self.ipfs_privkey)
|
|
||||||
log.debug("cleared: keygen.ipfs_privkey")
|
|
||||||
if hasattr(self, 'jwk'):
|
|
||||||
if hasattr(self.jwk, 'd') and self.jwk.d:
|
|
||||||
clearmem(self.jwk.d)
|
|
||||||
log.debug("cleared: keygen.jwk.d")
|
|
||||||
if hasattr(self, 'password') and self.password:
|
|
||||||
clearmem(self.password)
|
|
||||||
log.debug("cleared: keygen.password")
|
|
||||||
if hasattr(self, 'pgp_secret_armor') and self.pgp_secret_armor:
|
|
||||||
clearmem(self.pgp_secret_armor)
|
|
||||||
log.debug("cleared: keygen.pgp_secret_armor")
|
|
||||||
if hasattr(self, 'pgpy'):
|
|
||||||
if hasattr(self.pgpy._key.keymaterial, 'p') and self.pgpy._key.keymaterial.p and not isinstance(self.pgpy._key.keymaterial.p, pgpy.packet.fields.ECPoint):
|
|
||||||
clearmem(self.pgpy._key.keymaterial.p)
|
|
||||||
log.debug("cleared: keygen.pgpy._key.material.p")
|
|
||||||
if hasattr(self.pgpy._key.keymaterial, 'q') and self.pgpy._key.keymaterial.q:
|
|
||||||
clearmem(self.pgpy._key.keymaterial.q)
|
|
||||||
log.debug("cleared: keygen.pgpy._key.material.q")
|
|
||||||
if hasattr(self.pgpy._key.keymaterial, 's') and self.pgpy._key.keymaterial.s:
|
|
||||||
clearmem(self.pgpy._key.keymaterial.s)
|
|
||||||
log.debug("cleared: keygen.pgpy._key.material.s")
|
|
||||||
if hasattr(self, 'username') and self.username:
|
|
||||||
clearmem(self.username)
|
|
||||||
log.debug("cleared: keygen.username")
|
|
||||||
|
|
||||||
def _invalid_type(self):
|
|
||||||
log.debug("keygen._invalid_type()")
|
|
||||||
self.parser.error(f"type {self.type} is not valid.")
|
|
||||||
|
|
||||||
def _load_config(self):
|
|
||||||
log.debug("keygen._load_config()")
|
|
||||||
self.config = configparser.RawConfigParser()
|
|
||||||
config_dir = os.path.join(os.environ.get('XDG_CONFIG_HOME', os.path.expanduser('~/.config')), 'dpgpid')
|
|
||||||
log.debug("config_dir=%s" % config_dir)
|
|
||||||
self.config.read( [config_dir + '/keygen.conf'] )
|
|
||||||
|
|
||||||
def _output(self, public_key, secret_key, public_key_prefix, secret_key_prefix):
|
|
||||||
log.debug("keygen._output()")
|
|
||||||
if self.output is None:
|
|
||||||
self._output_text(public_key, secret_key, public_key_prefix, secret_key_prefix)
|
|
||||||
else:
|
|
||||||
self._output_file()
|
|
||||||
os.chmod(self.output, 0o600)
|
|
||||||
self._cleanup()
|
|
||||||
|
|
||||||
def _output_file(self):
|
|
||||||
log.debug("keygen._output_file()")
|
|
||||||
try:
|
|
||||||
if self.format == 'dewif':
|
|
||||||
if not hasattr(self, 'duniterpy'):
|
|
||||||
self.duniterpy_from_ed25519_seed_bytes()
|
|
||||||
if not self.password:
|
|
||||||
with pynentry.PynEntry() as p:
|
|
||||||
p.description = f"""Data in DEWIF file needs to be encrypted.
|
|
||||||
Please enter a password to encrypt seed.
|
|
||||||
"""
|
|
||||||
p.prompt = 'Passphrase:'
|
|
||||||
try:
|
|
||||||
self.password = p.get_pin()
|
|
||||||
except pynentry.PinEntryCancelled:
|
|
||||||
log.warning('Cancelled! Goodbye.')
|
|
||||||
self._cleanup()
|
|
||||||
exit(1)
|
|
||||||
self.duniterpy.save_dewif_v1_file(self.output, self.password)
|
|
||||||
elif self.format == 'ewif':
|
|
||||||
if not hasattr(self, 'duniterpy'):
|
|
||||||
self.duniterpy_from_ed25519_seed_bytes()
|
|
||||||
if not self.password:
|
|
||||||
with pynentry.PynEntry() as p:
|
|
||||||
p.description = f"""Data in EWIF file needs to be encrypted.
|
|
||||||
Please enter a password to encrypt seed.
|
|
||||||
"""
|
|
||||||
p.prompt = 'Passphrase:'
|
|
||||||
try:
|
|
||||||
self.password = p.get_pin()
|
|
||||||
except pynentry.PinEntryCancelled:
|
|
||||||
log.warning('Cancelled! Goodbye.')
|
|
||||||
self._cleanup()
|
|
||||||
exit(1)
|
|
||||||
self.duniterpy.save_ewif_file(self.output, self.password)
|
|
||||||
elif self.format == 'jwk':
|
|
||||||
if not hasattr(self, 'jwk'):
|
|
||||||
self.jwk_from_ed25519()
|
|
||||||
with open(self.output, "w") as file:
|
|
||||||
file.write(self.jwk.export())
|
|
||||||
elif self.format == 'nacl':
|
|
||||||
if not hasattr(self, 'duniterpy'):
|
|
||||||
self.duniterpy_from_ed25519_seed_bytes()
|
|
||||||
self.duniterpy.save_private_key(self.output)
|
|
||||||
elif self.format == 'pb2':
|
|
||||||
if not hasattr(self, 'ed25519_secret_protobuf'):
|
|
||||||
self.protobuf_from_ed25519()
|
|
||||||
with open(self.output, "wb") as file:
|
|
||||||
file.write(self.ed25519_secret_protobuf)
|
|
||||||
elif self.format == 'pubsec':
|
|
||||||
if not hasattr(self, 'duniterpy'):
|
|
||||||
self.duniterpy_from_ed25519_seed_bytes()
|
|
||||||
self.duniterpy.save_pubsec_file(self.output)
|
|
||||||
elif self.format == 'seed':
|
|
||||||
if not hasattr(self, 'duniterpy'):
|
|
||||||
self.duniterpy_from_ed25519_seed_bytes()
|
|
||||||
self.duniterpy.save_seedhex_file(self.output)
|
|
||||||
elif self.format == 'wif':
|
|
||||||
if not hasattr(self, 'duniterpy'):
|
|
||||||
self.duniterpy_from_ed25519_seed_bytes()
|
|
||||||
self.duniterpy.save_wif_file(self.output)
|
|
||||||
else:
|
|
||||||
if not hasattr(self, 'ed25519_secret_pem_pkcs8'):
|
|
||||||
self.pem_pkcs8_from_ed25519()
|
|
||||||
with open(self.output, "w") as file:
|
|
||||||
file.write(self.ed25519_secret_pem_pkcs8)
|
|
||||||
except Exception as e:
|
|
||||||
log.error(f'Unable to output file {self.output}: {e}')
|
|
||||||
self._cleanup()
|
|
||||||
exit(2)
|
|
||||||
|
|
||||||
def _output_text(self, public_key, secret_key, public_key_prefix, secret_key_prefix):
|
|
||||||
log.debug("keygen._output_text()")
|
|
||||||
if self.keys or not self.secret:
|
|
||||||
print("%s" % ''.join([self.prefix * public_key_prefix, public_key]))
|
|
||||||
if self.keys or self.secret:
|
|
||||||
print("%s" % ''.join([self.prefix * secret_key_prefix, secret_key]))
|
|
||||||
|
|
||||||
def _run(self, argv):
|
|
||||||
args = self.parser.parse_args(argv)
|
|
||||||
vars(self).update(vars(args))
|
|
||||||
|
|
||||||
# display version
|
|
||||||
if args.version:
|
|
||||||
version()
|
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
# define log format
|
|
||||||
log_format='%(asctime)s %(levelname)s: %(message)s'
|
|
||||||
log_datefmt='%Y/%m/%d %H:%M:%S'
|
|
||||||
if args.debug:
|
|
||||||
log_level='DEBUG'
|
|
||||||
elif args.quiet:
|
|
||||||
log_level='ERROR'
|
|
||||||
elif args.verbose:
|
|
||||||
log_level='INFO'
|
|
||||||
else:
|
|
||||||
log_level='WARNING'
|
|
||||||
log.basicConfig(format=log_format, datefmt=log_datefmt, level=log_level)
|
|
||||||
log.debug("keygen.run(%s)" % argv)
|
|
||||||
|
|
||||||
self._check_args(args)
|
|
||||||
self._load_config()
|
|
||||||
self.gpg = gpg.Context(armor=True, offline=True)
|
|
||||||
self.gpg.set_passphrase_cb(self.gpg_passphrase_cb)
|
|
||||||
self.ed25519(args)
|
|
||||||
method = getattr(self, f'do_{self.type}', self._invalid_type)
|
|
||||||
return method()
|
|
||||||
|
|
||||||
def b58mh_from_protobuf(self):
|
|
||||||
log.debug("keygen.b58mh_from_protobuf()")
|
|
||||||
try:
|
|
||||||
self.ed25519_public_b58mh = base58.b58encode(self.ed25519_public_protobuf).decode('ascii')
|
|
||||||
self.ed25519_secret_b58mh = base58.b58encode(self.ed25519_secret_protobuf).decode('ascii')
|
|
||||||
except Exception as e:
|
|
||||||
log.error(f'Unable to get b58mh from protobuf: {e}')
|
|
||||||
self._cleanup()
|
|
||||||
exit(2)
|
|
||||||
log.debug("keygen.ed25519_public_b58mh=%s" % self.ed25519_public_b58mh)
|
|
||||||
log.debug("keygen.ed25519_secret_b58mh=%s" % self.ed25519_secret_b58mh)
|
|
||||||
|
|
||||||
def b64mh_from_protobuf(self):
|
|
||||||
log.debug("keygen.b64mh_from_protobuf()")
|
|
||||||
try:
|
|
||||||
self.ed25519_public_b64mh = base64.b64encode(self.ed25519_public_protobuf).decode('ascii')
|
|
||||||
self.ed25519_secret_b64mh = base64.b64encode(self.ed25519_secret_protobuf).decode('ascii')
|
|
||||||
except Exception as e:
|
|
||||||
log.error(f'Unable to get b64mh from protobuf: {e}')
|
|
||||||
self._cleanup()
|
|
||||||
exit(2)
|
|
||||||
log.debug("keygen.ed25519_public_b64mh=%s" % self.ed25519_public_b64mh)
|
|
||||||
log.debug("keygen.ed25519_secret_b64mh=%s" % self.ed25519_secret_b64mh)
|
|
||||||
|
|
||||||
def base58_from_ed25519(self):
|
|
||||||
log.debug("keygen.base58_from_ed25519()")
|
|
||||||
try:
|
|
||||||
self.ed25519_public_base58 = base58.b58encode(self.ed25519_public_bytes).decode('ascii')
|
|
||||||
self.ed25519_secret_base58 = base58.b58encode(self.ed25519_secret_bytes).decode('ascii')
|
|
||||||
except Exception as e:
|
|
||||||
log.error(f'Unable to get base58 from ed25519: {e}')
|
|
||||||
self._cleanup()
|
|
||||||
exit(2)
|
|
||||||
log.debug("keygen.ed25519_public_base58=%s" % self.ed25519_public_base58)
|
|
||||||
log.debug("keygen.ed25519_secret_base58=%s" % self.ed25519_secret_base58)
|
|
||||||
|
|
||||||
def base64_from_ed25519(self):
|
|
||||||
log.debug("keygen.base64_from_ed25519()")
|
|
||||||
try:
|
|
||||||
self.ed25519_public_base64 = base64.b64encode(self.ed25519_public_bytes).decode('ascii')
|
|
||||||
self.ed25519_secret_base64 = base64.b64encode(self.ed25519_secret_bytes).decode('ascii')
|
|
||||||
except Exception as e:
|
|
||||||
log.error(f'Unable to get base64 from ed25519: {e}')
|
|
||||||
self._cleanup()
|
|
||||||
exit(2)
|
|
||||||
log.debug("keygen.ed25519_public_base64=%s" % self.ed25519_public_base64)
|
|
||||||
log.debug("keygen.ed25519_secret_base64=%s" % self.ed25519_secret_base64)
|
|
||||||
|
|
||||||
def do_b58mh(self):
|
|
||||||
log.debug("keygen.do_b58mh()")
|
|
||||||
self.protobuf_from_ed25519()
|
|
||||||
self.b58mh_from_protobuf()
|
|
||||||
self._output(self.ed25519_public_b58mh, self.ed25519_secret_b58mh, 'pub: ', 'sec: ')
|
|
||||||
|
|
||||||
def do_b64mh(self):
|
|
||||||
log.debug("keygen.do_b64mh()")
|
|
||||||
self.protobuf_from_ed25519()
|
|
||||||
self.b64mh_from_protobuf()
|
|
||||||
self._output(self.ed25519_public_b64mh, self.ed25519_secret_b64mh, 'pub: ', 'sec: ')
|
|
||||||
|
|
||||||
def do_base58(self):
|
|
||||||
log.debug("keygen.do_base58()")
|
|
||||||
self.base58_from_ed25519()
|
|
||||||
self._output(self.ed25519_public_base58, self.ed25519_secret_base58, 'pub: ', 'sec: ')
|
|
||||||
|
|
||||||
def do_base64(self):
|
|
||||||
log.debug("keygen.do_base64()")
|
|
||||||
self.base64_from_ed25519()
|
|
||||||
self._output(self.ed25519_public_base64, self.ed25519_secret_base64, 'pub: ', 'sec: ')
|
|
||||||
|
|
||||||
def do_duniter(self):
|
|
||||||
log.debug("keygen.do_duniter()")
|
|
||||||
if not self.format:
|
|
||||||
self.format = 'pubsec'
|
|
||||||
self.base58_from_ed25519()
|
|
||||||
self._output(self.ed25519_public_base58, self.ed25519_secret_base58, 'pub: ', 'sec: ')
|
|
||||||
|
|
||||||
def do_ipfs(self):
|
|
||||||
log.debug("keygen.do_ipfs()")
|
|
||||||
self.protobuf_from_ed25519()
|
|
||||||
self.b58mh_from_protobuf()
|
|
||||||
self.b64mh_from_protobuf()
|
|
||||||
self._output(self.ed25519_public_b58mh, self.ed25519_secret_b64mh, 'PeerID: ', 'PrivKEY: ')
|
|
||||||
|
|
||||||
def do_jwk(self):
|
|
||||||
log.debug("keygen.do_jwk()")
|
|
||||||
self.jwk_from_ed25519()
|
|
||||||
self._output(self.jwk.export_public(), self.jwk.export_private(), 'pub: ', 'sec: ')
|
|
||||||
|
|
||||||
def duniterpy_from_credentials(self):
|
|
||||||
log.debug("keygen.duniterpy_from_credentials()")
|
|
||||||
try:
|
|
||||||
scrypt_params = duniterpy.key.scrypt_params.ScryptParams(
|
|
||||||
int(self.config.get('scrypt', 'n')) if self.config.has_option('scrypt', 'n') else 4096,
|
|
||||||
int(self.config.get('scrypt', 'r')) if self.config.has_option('scrypt', 'r') else 16,
|
|
||||||
int(self.config.get('scrypt', 'p')) if self.config.has_option('scrypt', 'p') else 1,
|
|
||||||
int(self.config.get('scrypt', 'sl')) if self.config.has_option('scrypt', 'sl') else 32,
|
|
||||||
)
|
|
||||||
if not self.password:
|
|
||||||
with pynentry.PynEntry() as p:
|
|
||||||
p.description = f"""Please enter the passord for username "{self.username}"."""
|
|
||||||
p.prompt = 'Passsord:'
|
|
||||||
try:
|
|
||||||
self.password = p.get_pin()
|
|
||||||
except pynentry.PinEntryCancelled:
|
|
||||||
log.warning('Cancelled! Goodbye.')
|
|
||||||
self._cleanup()
|
|
||||||
exit(1)
|
|
||||||
self.duniterpy = duniterpy.key.SigningKey.from_credentials(
|
|
||||||
self.username,
|
|
||||||
self.password,
|
|
||||||
scrypt_params
|
|
||||||
)
|
|
||||||
except Exception as e:
|
|
||||||
log.error(f'Unable to get duniter from credentials: {e}')
|
|
||||||
self._cleanup()
|
|
||||||
exit(2)
|
|
||||||
log.debug("keygen.duniterpy.seed: %s" % self.duniterpy.seed)
|
|
||||||
|
|
||||||
def duniterpy_from_ed25519_seed_bytes(self):
|
|
||||||
log.debug("keygen.duniterpy_from_ed25519_seed_bytes()")
|
|
||||||
try:
|
|
||||||
self.duniterpy = duniterpy.key.SigningKey(self.ed25519_seed_bytes)
|
|
||||||
except Exception as e:
|
|
||||||
log.error(f'Unable to get duniterpy from ed25519 seed bytes: {e}')
|
|
||||||
self._cleanup()
|
|
||||||
exit(2)
|
|
||||||
log.debug("keygen.duniterpy.seed: %s" % self.duniterpy.seed)
|
|
||||||
|
|
||||||
def duniterpy_from_file(self):
|
|
||||||
log.debug("keygen.duniterpy_from_file()")
|
|
||||||
try:
|
|
||||||
with open(self.input, 'r') as file:
|
|
||||||
lines = file.readlines()
|
|
||||||
if len(lines) > 0:
|
|
||||||
line = lines[0].strip()
|
|
||||||
regex_ewif = re.compile('^Type: EWIF$')
|
|
||||||
regex_jwk = re.compile('^\\s*{\\s*"crv":\\s*"Ed25519",\\s*"d":\\s*"(.)+",\\s*"kty":\\s*"OKP",\\s*"x":\\s*"(.)+"\\s*}')
|
|
||||||
regex_nacl = re.compile('^\\s*{\\s*"priv":\\s*"[0-9a-fA-F]+",\\s*"verify":\\s*"[0-9a-fA-F]+",\\s*"sign":\\s*"[0-9a-fA-F]+"\\s*}')
|
|
||||||
regex_pem = re.compile('^-----BEGIN PRIVATE KEY-----$')
|
|
||||||
regex_pubsec = re.compile('^Type: PubSec$')
|
|
||||||
regex_seed = re.compile('^[0-9a-fA-F]{64}$')
|
|
||||||
regex_ssb = re.compile('\\s*{\\s*"curve":\\s*"ed25519",\\s*"public":\\s*"(.+)\\.ed25519",\\s*"private":\\s*"(.+)\\.ed25519",\\s*"id":\\s*"@(.+).ed25519"\\s*}')
|
|
||||||
regex_wif = re.compile('^Type: WIF$')
|
|
||||||
if re.search(regex_ewif, line):
|
|
||||||
log.info("input file format detected: ewif")
|
|
||||||
if not self.password:
|
|
||||||
with pynentry.PynEntry() as p:
|
|
||||||
p.description = f"""Data in EWIF file is encrypted.
|
|
||||||
Please enter a password to decrypt seed.
|
|
||||||
"""
|
|
||||||
p.prompt = 'Passphrase:'
|
|
||||||
try:
|
|
||||||
self.password = p.get_pin()
|
|
||||||
except pynentry.PinEntryCancelled:
|
|
||||||
log.warning('Cancelled! Goodbye.')
|
|
||||||
self._cleanup()
|
|
||||||
exit(1)
|
|
||||||
self.duniterpy = duniterpy.key.SigningKey.from_ewif_file(self.input, self.password)
|
|
||||||
elif re.search(regex_jwk, line):
|
|
||||||
log.info("input file format detected: jwk")
|
|
||||||
self.jwk_from_json(line)
|
|
||||||
self.ed25519_seed_bytes_from_jwk()
|
|
||||||
self.duniterpy_from_ed25519_seed_bytes()
|
|
||||||
elif re.search(regex_nacl, line):
|
|
||||||
log.info("input file format detected: nacl")
|
|
||||||
self.duniterpy = duniterpy.key.SigningKey.from_private_key(self.input)
|
|
||||||
elif re.search(regex_pem, line):
|
|
||||||
log.info("input file format detected: pem")
|
|
||||||
self.ed25519_seed_bytes_from_pem(''.join(lines).encode())
|
|
||||||
self.duniterpy_from_ed25519_seed_bytes()
|
|
||||||
elif re.search(regex_pubsec, line):
|
|
||||||
log.info("input file format detected: pubsec")
|
|
||||||
self.duniterpy = duniterpy.key.SigningKey.from_pubsec_file(self.input)
|
|
||||||
elif re.search(regex_seed, line):
|
|
||||||
log.info("input file format detected: seed")
|
|
||||||
self.duniterpy = duniterpy.key.SigningKey.from_seedhex_file(self.input)
|
|
||||||
elif re.search(regex_ssb, line):
|
|
||||||
log.info("input file format detected: ssb")
|
|
||||||
self.duniterpy = duniterpy.key.SigningKey.from_ssb_file(self.input)
|
|
||||||
elif re.search(regex_wif, line):
|
|
||||||
log.info("input file format detected: wif")
|
|
||||||
self.duniterpy = duniterpy.key.SigningKey.from_wif_file(self.input)
|
|
||||||
elif len(line.split(' ')) == 12:
|
|
||||||
log.info("input file format detected: mnemonic")
|
|
||||||
self.username = line
|
|
||||||
self.duniterpy_from_mnemonic()
|
|
||||||
elif len(lines) > 1:
|
|
||||||
log.info("input file format detected: credentials")
|
|
||||||
self.username = line
|
|
||||||
self.password = lines[1].strip()
|
|
||||||
self.duniterpy_from_credentials()
|
|
||||||
else:
|
|
||||||
raise NotImplementedError('unknown input file format.')
|
|
||||||
else:
|
|
||||||
raise NotImplementedError('empty file.')
|
|
||||||
except UnicodeDecodeError as e:
|
|
||||||
try:
|
|
||||||
with open(self.input, 'rb') as file:
|
|
||||||
lines = file.readlines()
|
|
||||||
if len(lines) > 0:
|
|
||||||
line = lines[0].strip()
|
|
||||||
regex_dewif = re.compile(b'^\x00\x00\x00\x01\x00\x00\x00\x01')
|
|
||||||
regex_pb2 = re.compile(b'^\x08\x01\x12@')
|
|
||||||
if re.search(regex_dewif, line):
|
|
||||||
log.info("input file format detected: dewif")
|
|
||||||
if not self.password:
|
|
||||||
with pynentry.PynEntry() as p:
|
|
||||||
p.description = f"""Data in DEWIF file is encrypted.
|
|
||||||
Please enter a password to decrypt seed.
|
|
||||||
"""
|
|
||||||
p.prompt = 'Passphrase:'
|
|
||||||
try:
|
|
||||||
self.password = p.get_pin()
|
|
||||||
except pynentry.PinEntryCancelled:
|
|
||||||
log.warning('Cancelled! Goodbye.')
|
|
||||||
self._cleanup()
|
|
||||||
exit(1)
|
|
||||||
self.duniterpy = duniterpy.key.SigningKey.from_dewif_file(self.input, self.password)
|
|
||||||
if re.search(regex_pb2, line):
|
|
||||||
log.info("input file format detected: pb2")
|
|
||||||
self.ed25519_secret_protobuf = line
|
|
||||||
self.ed25519_seed_bytes_from_protobuf()
|
|
||||||
self.duniterpy_from_ed25519_seed_bytes()
|
|
||||||
else:
|
|
||||||
raise NotImplementedError('unknown input file format.')
|
|
||||||
else:
|
|
||||||
raise NotImplementedError('empty file.')
|
|
||||||
except Exception as e:
|
|
||||||
log.error(f'Unable to get duniterpy from file {self.input}: {e}')
|
|
||||||
self._cleanup()
|
|
||||||
exit(2)
|
|
||||||
except Exception as e:
|
|
||||||
log.error(f'Unable to get duniterpy from file {self.input}: {e}')
|
|
||||||
self._cleanup()
|
|
||||||
exit(2)
|
|
||||||
log.debug("keygen.duniterpy.seed: %s" % self.duniterpy.seed)
|
|
||||||
|
|
||||||
def duniterpy_from_mnemonic(self):
|
|
||||||
log.debug("keygen.duniterpy_from_mnemonic()")
|
|
||||||
try:
|
|
||||||
scrypt_params = duniterpy.key.scrypt_params.ScryptParams(
|
|
||||||
int(self.config.get('scrypt', 'n')) if self.config.has_option('scrypt', 'n') else 4096,
|
|
||||||
int(self.config.get('scrypt', 'r')) if self.config.has_option('scrypt', 'r') else 16,
|
|
||||||
int(self.config.get('scrypt', 'p')) if self.config.has_option('scrypt', 'p') else 1,
|
|
||||||
int(self.config.get('scrypt', 'sl')) if self.config.has_option('scrypt', 'sl') else 32,
|
|
||||||
)
|
|
||||||
self.duniterpy = duniterpy.key.SigningKey.from_dubp_mnemonic(
|
|
||||||
self.username,
|
|
||||||
scrypt_params
|
|
||||||
)
|
|
||||||
except Exception as e:
|
|
||||||
log.error(f'Unable to get duniterpy from mnemonic: {e}')
|
|
||||||
self._cleanup()
|
|
||||||
exit(2)
|
|
||||||
log.debug("keygen.duniterpy.seed: %s" % self.duniterpy.seed)
|
|
||||||
|
|
||||||
def ed25519(self, args):
|
|
||||||
log.debug("keygen.ed25519(%s)" % args)
|
|
||||||
if args.gpg:
|
|
||||||
self.ed25519_from_gpg()
|
|
||||||
else:
|
|
||||||
if self.input:
|
|
||||||
self.duniterpy_from_file()
|
|
||||||
else:
|
|
||||||
if self.mnemonic:
|
|
||||||
self.duniterpy_from_mnemonic()
|
|
||||||
else:
|
|
||||||
self.duniterpy_from_credentials()
|
|
||||||
self.ed25519_from_duniterpy()
|
|
||||||
|
|
||||||
def ed25519_from_duniterpy(self):
|
|
||||||
log.debug("keygen.ed25519_from_duniterpy()")
|
|
||||||
try:
|
|
||||||
self.ed25519_seed_bytes_from_duniterpy()
|
|
||||||
self.ed25519_from_seed_bytes()
|
|
||||||
except:
|
|
||||||
log.error(f'Unable to get ed25519 from duniterpy: {e}')
|
|
||||||
self._cleanup()
|
|
||||||
exit(2)
|
|
||||||
|
|
||||||
def ed25519_from_gpg(self):
|
|
||||||
log.debug("keygen.ed25519_from_gpg()")
|
|
||||||
try:
|
|
||||||
self.pgpy_from_gpg()
|
|
||||||
self.ed25519_from_pgpy()
|
|
||||||
except Exception as e:
|
|
||||||
log.error(f'Unable to get ed25519 from pgp: {e}')
|
|
||||||
self._cleanup()
|
|
||||||
exit(2)
|
|
||||||
|
|
||||||
def ed25519_from_pgpy(self):
|
|
||||||
log.debug("keygen.ed25519_from_pgpy()")
|
|
||||||
try:
|
|
||||||
log.debug("keygen.pgpy.fingerprint.keyid=%s" % self.pgpy.fingerprint.keyid)
|
|
||||||
log.debug("keygen.pgpy.is_protected=%s" % self.pgpy.is_protected)
|
|
||||||
if self.pgpy.is_protected:
|
|
||||||
if not self.password:
|
|
||||||
with pynentry.PynEntry() as p:
|
|
||||||
p.description = f"""The exported pgp key id "{self.pgpy.fingerprint.keyid}" of user "{self.username}" is password protected.
|
|
||||||
Please enter the passphrase again to unlock it.
|
|
||||||
"""
|
|
||||||
p.prompt = 'Passphrase:'
|
|
||||||
try:
|
|
||||||
self.password = p.get_pin()
|
|
||||||
except pynentry.PinEntryCancelled:
|
|
||||||
log.warning('Cancelled! Goodbye.')
|
|
||||||
self._cleanup()
|
|
||||||
exit(1)
|
|
||||||
try:
|
|
||||||
with warnings.catch_warnings():
|
|
||||||
# remove CryptographyDeprecationWarning about deprecated
|
|
||||||
# SymmetricKeyAlgorithm IDEA, CAST5 and Blowfish (PGPy v0.5.4)
|
|
||||||
warnings.simplefilter('ignore')
|
|
||||||
with self.pgpy.unlock(self.password):
|
|
||||||
assert self.pgpy.is_unlocked
|
|
||||||
log.debug("keygen.pgpy.is_unlocked=%s" % self.pgpy.is_unlocked)
|
|
||||||
self.ed25519_seed_bytes_from_pgpy()
|
|
||||||
except Exception as e:
|
|
||||||
log.error(f"""Unable to unlock pgp secret key id "{self.pgpy.fingerprint.keyid}" of user "{self.username}": {e}""")
|
|
||||||
self._cleanup()
|
|
||||||
exit(2)
|
|
||||||
else:
|
|
||||||
self.ed25519_seed_bytes_from_pgpy()
|
|
||||||
self.ed25519_from_seed_bytes()
|
|
||||||
except Exception as e:
|
|
||||||
log.error(f'Unable to get ed25519 seed bytes from pgpy: {e}')
|
|
||||||
self._cleanup()
|
|
||||||
exit(2)
|
|
||||||
|
|
||||||
def ed25519_from_seed_bytes(self):
|
|
||||||
log.debug("keygen.ed25519_from_seed_bytes()")
|
|
||||||
try:
|
|
||||||
self.ed25519_public_bytes, self.ed25519_secret_bytes = nacl.bindings.crypto_sign_seed_keypair(self.ed25519_seed_bytes)
|
|
||||||
self.ed25519 = ed25519.Ed25519PrivateKey.from_private_bytes(self.ed25519_seed_bytes)
|
|
||||||
except Exception as e:
|
|
||||||
log.error(f'Unable to get ed25519 from seed bytes: {e}')
|
|
||||||
self._cleanup()
|
|
||||||
exit(2)
|
|
||||||
log.debug("keygen.ed25519_public_bytes=%s" % self.ed25519_public_bytes)
|
|
||||||
log.debug("keygen.ed25519_secret_bytes=%s" % self.ed25519_secret_bytes)
|
|
||||||
|
|
||||||
def ed25519_seed_bytes_from_duniterpy(self):
|
|
||||||
log.debug("keygen.ed25519_seed_bytes_from_duniterpy()")
|
|
||||||
try:
|
|
||||||
self.ed25519_seed_bytes = self.duniterpy.sk[:32]
|
|
||||||
except Exception as e:
|
|
||||||
log.error(f'Unable to get ed25519 seed bytes from duniterpy: {e}')
|
|
||||||
self._cleanup()
|
|
||||||
exit(2)
|
|
||||||
log.debug("keygen.ed25519_seed_bytes=%s" % self.ed25519_seed_bytes)
|
|
||||||
|
|
||||||
def ed25519_seed_bytes_from_jwk(self):
|
|
||||||
log.debug("keygen.ed25519_seed_bytes_from_jwk()")
|
|
||||||
try:
|
|
||||||
self.ed25519_seed_bytes = self.jwk._okp_pri().private_bytes(encoding=serialization.Encoding.Raw, format=serialization.PrivateFormat.Raw, encryption_algorithm=serialization.NoEncryption())
|
|
||||||
except Exception as e:
|
|
||||||
log.error(f'Unable to get ed25519 seed bytes from jwk: {e}')
|
|
||||||
self._cleanup()
|
|
||||||
exit(2)
|
|
||||||
|
|
||||||
def ed25519_seed_bytes_from_pem(self, pem):
|
|
||||||
log.debug("keygen.ed25519_seed_bytes_from_pem()")
|
|
||||||
try:
|
|
||||||
self.ed25519_seed_bytes = serialization.load_pem_private_key(pem, password=None).private_bytes(encoding=serialization.Encoding.Raw, format=serialization.PrivateFormat.Raw, encryption_algorithm=serialization.NoEncryption())
|
|
||||||
except Exception as e:
|
|
||||||
log.error(f'Unable to get ed25519 seed bytes from pem: {e}')
|
|
||||||
self._cleanup()
|
|
||||||
exit(2)
|
|
||||||
|
|
||||||
def ed25519_seed_bytes_from_pgpy(self):
|
|
||||||
log.debug("keygen.ed25519_seed_bytes_from_pgpy()")
|
|
||||||
try:
|
|
||||||
self.pgpy_key_type()
|
|
||||||
if self.pgpy_key_type == 'RSA':
|
|
||||||
log.debug("keygen.pgpy._key.keymaterial.p=%s" % self.pgpy._key.keymaterial.p)
|
|
||||||
log.debug("keygen.pgpy._key.keymaterial.q=%s" % self.pgpy._key.keymaterial.q)
|
|
||||||
# custom seed: use sha256 hash of (p + q)
|
|
||||||
self.ed25519_seed_bytes = nacl.bindings.crypto_hash_sha256(long_to_bytes(self.pgpy._key.keymaterial.p + self.pgpy._key.keymaterial.q))
|
|
||||||
elif self.pgpy_key_type in ('ECDSA', 'EdDSA', 'ECDH'):
|
|
||||||
log.debug("keygen.pgpy._key.keymaterial.s=%s" % self.pgpy._key.keymaterial.s)
|
|
||||||
self.ed25519_seed_bytes = long_to_bytes(self.pgpy._key.keymaterial.s)
|
|
||||||
else:
|
|
||||||
raise NotImplementedError(f"getting seed from {self.pgpy_key_type} key is not implemented")
|
|
||||||
except Exception as e:
|
|
||||||
log.error(f'Unable to get ed25519 seed bytes from pgpy: {e}')
|
|
||||||
self._cleanup()
|
|
||||||
exit(2)
|
|
||||||
log.debug("keygen.ed25519_seed_bytes=%s" % self.ed25519_seed_bytes)
|
|
||||||
|
|
||||||
def ed25519_seed_bytes_from_protobuf(self):
|
|
||||||
log.debug("keygen.ed25519_seed_bytes_from_protobuf()")
|
|
||||||
try:
|
|
||||||
self.ed25519_seed_bytes = self.ed25519_secret_protobuf.lstrip(b'\x08\x01\x12@')[:32]
|
|
||||||
except Exception as e:
|
|
||||||
log.error(f'Unable to get ed25519 seed bytes from protobuf: {e}')
|
|
||||||
self._cleanup()
|
|
||||||
exit(2)
|
|
||||||
log.debug("keygen.ed25519_seed_bytes=%s" % self.ed25519_seed_bytes)
|
|
||||||
|
|
||||||
def gpg_passphrase_cb(self, uid_hint, passphrase_info, prev_was_bad):
|
|
||||||
log.debug("keygen.gpg_passphrase_cb(%s, %s, %s)" % (uid_hint, passphrase_info, prev_was_bad))
|
|
||||||
return self.password
|
|
||||||
|
|
||||||
def jwk_from_ed25519(self):
|
|
||||||
log.debug("keygen.jwk_from_ed25519()")
|
|
||||||
try:
|
|
||||||
self.jwk = jwk.JWK.from_pyca(self.ed25519)
|
|
||||||
except Exception as e:
|
|
||||||
log.error(f'Unable to get jwk from ed25519: {e}')
|
|
||||||
self._cleanup()
|
|
||||||
exit(2)
|
|
||||||
|
|
||||||
def jwk_from_json(self, json):
|
|
||||||
log.debug("keygen.jwk_from_json()")
|
|
||||||
try:
|
|
||||||
self.jwk = jwk.JWK.from_json(json)
|
|
||||||
except Exception as e:
|
|
||||||
log.error(f'Unable to get jwk from json: {e}')
|
|
||||||
self._cleanup()
|
|
||||||
exit(2)
|
|
||||||
|
|
||||||
def pem_pkcs8_from_ed25519(self):
|
|
||||||
log.debug("keygen.pem_pkcs8_from_ed25519()")
|
|
||||||
try:
|
|
||||||
self.ed25519_secret_pem_pkcs8 = self.ed25519.private_bytes(encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.PKCS8, encryption_algorithm=serialization.NoEncryption()).decode('ascii')
|
|
||||||
except Exception as e:
|
|
||||||
log.error(f'Unable to get pem pkcs8 from ed25519: {e}')
|
|
||||||
self._cleanup()
|
|
||||||
exit(2)
|
|
||||||
log.debug("keygen.ed25519_secret_pem_pkcs8=%s" % self.ed25519_secret_pem_pkcs8)
|
|
||||||
|
|
||||||
def pgpy_from_gpg(self):
|
|
||||||
log.debug("keygen.pgpy_from_gpg()")
|
|
||||||
try:
|
|
||||||
self.gpg_seckeys = list(self.gpg.keylist(pattern=self.username, secret=True))
|
|
||||||
log.debug("keygen.gpg_seckeys=%s" % self.gpg_seckeys)
|
|
||||||
if not self.gpg_seckeys:
|
|
||||||
log.warning(f"""Unable to find any key matching username "{self.username}".""")
|
|
||||||
self._cleanup()
|
|
||||||
exit(1)
|
|
||||||
else:
|
|
||||||
self.gpg_seckey = self.gpg_seckeys[0]
|
|
||||||
log.info(f"""Found key id "{self.gpg_seckey.fpr}" matching username "{self.username}".""")
|
|
||||||
log.debug("keygen.gpg_seckey.expired=%s" % self.gpg_seckey.expired)
|
|
||||||
log.debug("keygen.gpg_seckey.fpr=%s" % self.gpg_seckey.fpr)
|
|
||||||
log.debug("keygen.gpg_seckey.revoked=%s" % self.gpg_seckey.revoked)
|
|
||||||
log.debug("keygen.gpg_seckey.uids=%s" % self.gpg_seckey.uids)
|
|
||||||
log.debug("keygen.gpg_seckey.owner_trust=%s" % self.gpg_seckey.owner_trust)
|
|
||||||
log.debug("keygen.gpg_seckey.last_update=%s" % self.gpg_seckey.last_update)
|
|
||||||
if self.password:
|
|
||||||
self.gpg.set_pinentry_mode(gpg.constants.PINENTRY_MODE_LOOPBACK)
|
|
||||||
self.pgp_public_armor = self.gpg.key_export(self.gpg_seckey.fpr)
|
|
||||||
self.pgp_secret_armor = self.gpg.key_export_secret(self.gpg_seckey.fpr)
|
|
||||||
log.debug("keygen.pgp_secret_armor=%s" % self.pgp_secret_armor)
|
|
||||||
if not self.pgp_secret_armor:
|
|
||||||
log.error(f"""Unable to export gpg secret key id "{self.gpg_seckey.fpr}" of user "{self.username}". Please check your password!""")
|
|
||||||
self._cleanup()
|
|
||||||
exit(2)
|
|
||||||
with warnings.catch_warnings():
|
|
||||||
# remove CryptographyDeprecationWarning about deprecated
|
|
||||||
# SymmetricKeyAlgorithm IDEA, CAST5 and Blowfish (PGPy v0.5.4)
|
|
||||||
warnings.simplefilter('ignore')
|
|
||||||
self.pgpy, _ = pgpy.PGPKey.from_blob(self.pgp_secret_armor)
|
|
||||||
except Exception as e:
|
|
||||||
log.error(f'Unable to get pgpy from gpg: {e}')
|
|
||||||
self._cleanup()
|
|
||||||
exit(2)
|
|
||||||
|
|
||||||
def pgpy_key_type(self):
|
|
||||||
log.debug("keygen.pgpy_key_type()")
|
|
||||||
if isinstance(self.pgpy._key.keymaterial, pgpy.packet.fields.RSAPriv):
|
|
||||||
self.pgpy_key_type = 'RSA'
|
|
||||||
elif isinstance(self.pgpy._key.keymaterial, pgpy.packet.fields.DSAPriv):
|
|
||||||
self.pgpy_key_type = 'DSA'
|
|
||||||
elif isinstance(self.pgpy._key.keymaterial, pgpy.packet.fields.ElGPriv):
|
|
||||||
self.pgpy_key_type = 'ElGamal'
|
|
||||||
elif isinstance(self.pgpy._key.keymaterial, pgpy.packet.fields.ECDSAPriv):
|
|
||||||
self.pgpy_key_type = 'ECDSA'
|
|
||||||
elif isinstance(self.pgpy._key.keymaterial, pgpy.packet.fields.EdDSAPriv):
|
|
||||||
self.pgpy_key_type = 'EdDSA'
|
|
||||||
elif isinstance(self.pgpy._key.keymaterial, pgpy.packet.fields.ECDHPriv):
|
|
||||||
self.pgpy_key_type = 'ECDH'
|
|
||||||
else:
|
|
||||||
self.pgpy_key_type = 'undefined'
|
|
||||||
log.debug("keygen.pgpy_key_type=%s" % self.pgpy_key_type)
|
|
||||||
|
|
||||||
def protobuf_from_ed25519(self):
|
|
||||||
# libp2p protobuf version 2
|
|
||||||
log.debug("keygen.protobuf_from_ed25519()")
|
|
||||||
try:
|
|
||||||
self.ed25519_public_protobuf = b'\x00$\x08\x01\x12 ' + self.ed25519_public_bytes
|
|
||||||
self.ed25519_secret_protobuf = b'\x08\x01\x12@' + self.ed25519_secret_bytes
|
|
||||||
except Exception as e:
|
|
||||||
log.error(f'Unable to get protobuf from ed25519: {e}')
|
|
||||||
self._cleanup()
|
|
||||||
exit(2)
|
|
||||||
log.debug("keygen.ed25519_public_protobuf=%s" % self.ed25519_public_protobuf)
|
|
||||||
log.debug("keygen.ed25519_secret_protobuf=%s" % self.ed25519_secret_protobuf)
|
|
||||||
|
|
||||||
##
|
|
||||||
# long_to_bytes comes from PyCrypto, which is released into Public Domain
|
|
||||||
# https://github.com/dlitz/pycrypto/blob/master/lib/Crypto/Util/number.py
|
|
||||||
def bytes_to_long(s):
|
|
||||||
"""bytes_to_long(string) : long
|
|
||||||
Convert a byte string to a long integer.
|
|
||||||
This is (essentially) the inverse of long_to_bytes().
|
|
||||||
"""
|
|
||||||
acc = 0
|
|
||||||
unpack = struct.unpack
|
|
||||||
length = len(s)
|
|
||||||
if length % 4:
|
|
||||||
extra = (4 - length % 4)
|
|
||||||
s = b'\000' * extra + s
|
|
||||||
length = length + extra
|
|
||||||
for i in range(0, length, 4):
|
|
||||||
acc = (acc << 32) + unpack('>I', s[i:i+4])[0]
|
|
||||||
return acc
|
|
||||||
|
|
||||||
def long_to_bytes(n, blocksize=0):
|
|
||||||
"""long_to_bytes(n:long, blocksize:int) : string
|
|
||||||
Convert a long integer to a byte string.
|
|
||||||
If optional blocksize is given and greater than zero, pad the front of the
|
|
||||||
byte string with binary zeros so that the length is a multiple of
|
|
||||||
blocksize.
|
|
||||||
"""
|
|
||||||
# after much testing, this algorithm was deemed to be the fastest
|
|
||||||
s = b''
|
|
||||||
n = int(n)
|
|
||||||
pack = struct.pack
|
|
||||||
while n > 0:
|
|
||||||
s = pack('>I', n & 0xffffffff) + s
|
|
||||||
n = n >> 32
|
|
||||||
# strip off leading zeros
|
|
||||||
for i in range(len(s)):
|
|
||||||
if s[i] != b'\000'[0]:
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
# only happens when n == 0
|
|
||||||
s = b'\000'
|
|
||||||
i = 0
|
|
||||||
s = s[i:]
|
|
||||||
# add back some pad bytes. this could be done more efficiently w.r.t. the
|
|
||||||
# de-padding being done above, but sigh...
|
|
||||||
if blocksize > 0 and len(s) % blocksize:
|
|
||||||
s = (blocksize - len(s) % blocksize) * b'\000' + s
|
|
||||||
return s
|
|
||||||
|
|
||||||
def main(argv=None):
|
|
||||||
if argv is None:
|
|
||||||
argv = sys.argv[1:]
|
|
||||||
|
|
||||||
cli = keygen()
|
|
||||||
return cli._run(argv)
|
|
||||||
|
|
||||||
def version(version=__version__):
|
|
||||||
print("%s v%s" % (sys.argv[0],version))
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
sys.exit(main())
|
|
16
search
|
@ -1,16 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
clear
|
|
||||||
echo "------------------------------------------------------------------------------"
|
|
||||||
if [ "$1" == "" ]; then
|
|
||||||
echo " Nothing to search for!"
|
|
||||||
else
|
|
||||||
echo " Searching for "$1" recursively. Please Wait..."
|
|
||||||
echo "------------------------------------------------------------------------------"
|
|
||||||
grep -h -r --exclude=B00 -H --colour=always "$1" ./
|
|
||||||
fi
|
|
||||||
echo "------------------------------------------------------------------------------"
|
|
||||||
if [ "$2" != "" ]; then
|
|
||||||
echo " To replace \"$1\" whith \"$2\", please run"
|
|
||||||
echo " grep -rl '$1' ./ | xargs sed -i 's~$1~$2~g'"
|
|
||||||
fi
|
|
||||||
## THIS IS A GREAT RETRO ENGINEERING AND CODING TOOLS
|
|
|
@ -1,40 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
################################################################################
|
|
||||||
# Author: Fred (support@qo-op.com)
|
|
||||||
# Version: 0.1
|
|
||||||
# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/)
|
|
||||||
################################################################################
|
|
||||||
MY_PATH="`dirname \"$0\"`" # relative
|
|
||||||
MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized
|
|
||||||
ME="${0##*/}"
|
|
||||||
|
|
||||||
echo "#############################################"
|
|
||||||
echo ">>>>>>>>>>> SYSTEMD SETUP "
|
|
||||||
echo "#############################################"
|
|
||||||
|
|
||||||
echo "CREATE SYSTEMD g1billet SERVICE >>>>>>>>>>>>>>>>>>"
|
|
||||||
cat > /tmp/g1billet.service <<EOF
|
|
||||||
[Unit]
|
|
||||||
Description=G1BILLET API
|
|
||||||
After=network.target
|
|
||||||
Requires=network.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
User=_USER_
|
|
||||||
RestartSec=1
|
|
||||||
Restart=always
|
|
||||||
ExecStart=_MYPATH_/G1BILLETS.sh daemon
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
EOF
|
|
||||||
|
|
||||||
sudo cp -f /tmp/g1billet.service /etc/systemd/system/
|
|
||||||
sudo sed -i "s~_USER_~${USER}~g" /etc/systemd/system/g1billet.service
|
|
||||||
sudo sed -i "s~_MYPATH_~${MY_PATH}~g" /etc/systemd/system/g1billet.service
|
|
||||||
|
|
||||||
sudo systemctl daemon-reload
|
|
||||||
sudo systemctl enable g1billet
|
|
||||||
sudo systemctl restart g1billet
|
|
||||||
|
|
Before Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 7.8 KiB |
Before Width: | Height: | Size: 104 KiB |
Before Width: | Height: | Size: 65 KiB |
Before Width: | Height: | Size: 68 KiB |
Before Width: | Height: | Size: 161 KiB |
Before Width: | Height: | Size: 147 KiB |
Before Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 39 KiB |
Before Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 97 KiB |
Before Width: | Height: | Size: 175 KiB |