Code consistency updates
- Improved formatting - Added comments - URL encoded values in netcontroller.performGET - Kept SQL statement case consistency
This commit is contained in:
parent
bdd1d9697b
commit
62cad7a6ea
@ -25,10 +25,12 @@ import configparser, sys, random, threading, hmac, hashlib, base64, time, math,
|
|||||||
from core import Core
|
from core import Core
|
||||||
import onionrutils
|
import onionrutils
|
||||||
class API:
|
class API:
|
||||||
''' Main http api (flask)'''
|
'''
|
||||||
|
Main HTTP API (Flask)
|
||||||
|
'''
|
||||||
def validateToken(self, token):
|
def validateToken(self, token):
|
||||||
'''
|
'''
|
||||||
Validate if the client token (hmac) matches the given token
|
Validate that the client token (hmac) matches the given token
|
||||||
'''
|
'''
|
||||||
if self.clientToken != token:
|
if self.clientToken != token:
|
||||||
return False
|
return False
|
||||||
@ -36,10 +38,11 @@ class API:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def __init__(self, config, debug):
|
def __init__(self, config, debug):
|
||||||
''' Initialize the api server, preping variables for later use
|
'''
|
||||||
This initilization defines all of the API entry points and handlers for the endpoints and errors
|
Initialize the api server, preping variables for later use
|
||||||
|
|
||||||
This also saves the used host (random localhost IP address) to the data folder in host.txt
|
This initilization defines all of the API entry points and handlers for the endpoints and errors
|
||||||
|
This also saves the used host (random localhost IP address) to the data folder in host.txt
|
||||||
'''
|
'''
|
||||||
if os.path.exists('dev-enabled'):
|
if os.path.exists('dev-enabled'):
|
||||||
self._developmentMode = True
|
self._developmentMode = True
|
||||||
@ -72,9 +75,10 @@ class API:
|
|||||||
@app.before_request
|
@app.before_request
|
||||||
def beforeReq():
|
def beforeReq():
|
||||||
'''
|
'''
|
||||||
Simply define the request as not having yet failed, before every request.
|
Simply define the request as not having yet failed, before every request.
|
||||||
'''
|
'''
|
||||||
self.requestFailed = False
|
self.requestFailed = False
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@app.after_request
|
@app.after_request
|
||||||
@ -87,6 +91,7 @@ class API:
|
|||||||
resp.headers["Content-Security-Policy"] = "default-src 'none'"
|
resp.headers["Content-Security-Policy"] = "default-src 'none'"
|
||||||
resp.headers['X-Frame-Options'] = 'deny'
|
resp.headers['X-Frame-Options'] = 'deny'
|
||||||
resp.headers['X-Content-Type-Options'] = "nosniff"
|
resp.headers['X-Content-Type-Options'] = "nosniff"
|
||||||
|
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
@app.route('/client/')
|
@app.route('/client/')
|
||||||
@ -112,6 +117,7 @@ class API:
|
|||||||
elapsed = endTime - startTime
|
elapsed = endTime - startTime
|
||||||
if elapsed < self._privateDelayTime:
|
if elapsed < self._privateDelayTime:
|
||||||
time.sleep(self._privateDelayTime - elapsed)
|
time.sleep(self._privateDelayTime - elapsed)
|
||||||
|
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
@app.route('/public/')
|
@app.route('/public/')
|
||||||
@ -149,17 +155,21 @@ class API:
|
|||||||
def notfound(err):
|
def notfound(err):
|
||||||
self.requestFailed = True
|
self.requestFailed = True
|
||||||
resp = Response("")
|
resp = Response("")
|
||||||
#resp.headers = getHeaders(resp)
|
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
@app.errorhandler(403)
|
@app.errorhandler(403)
|
||||||
def authFail(err):
|
def authFail(err):
|
||||||
self.requestFailed = True
|
self.requestFailed = True
|
||||||
resp = Response("403")
|
resp = Response("403")
|
||||||
|
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
@app.errorhandler(401)
|
@app.errorhandler(401)
|
||||||
def clientError(err):
|
def clientError(err):
|
||||||
self.requestFailed = True
|
self.requestFailed = True
|
||||||
resp = Response("Invalid request")
|
resp = Response("Invalid request")
|
||||||
|
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
logger.info('Starting client on ' + self.host + ':' + str(bindPort) + '...')
|
logger.info('Starting client on ' + self.host + ':' + str(bindPort) + '...')
|
||||||
@ -168,7 +178,9 @@ class API:
|
|||||||
app.run(host=self.host, port=bindPort, debug=True, threaded=True)
|
app.run(host=self.host, port=bindPort, debug=True, threaded=True)
|
||||||
|
|
||||||
def validateHost(self, hostType):
|
def validateHost(self, hostType):
|
||||||
''' Validate various features of the request including:
|
'''
|
||||||
|
Validate various features of the request including:
|
||||||
|
|
||||||
If private (/client/), is the host header local?
|
If private (/client/), is the host header local?
|
||||||
If public (/public/), is the host header onion or i2p?
|
If public (/public/), is the host header onion or i2p?
|
||||||
|
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
'''
|
|
||||||
Simply define terminal control codes (mainly colors)
|
|
||||||
'''
|
|
||||||
class Colors:
|
|
||||||
def __init__(self):
|
|
||||||
'''
|
|
||||||
PURPLE='\033[95m'
|
|
||||||
BLUE='\033[94m'
|
|
||||||
GREEN='\033[92m'
|
|
||||||
YELLOW='\033[93m'
|
|
||||||
RED='\033[91m'
|
|
||||||
BOLD='\033[1m'
|
|
||||||
UNDERLINE='\033[4m'
|
|
||||||
RESET="\x1B[m"
|
|
||||||
'''
|
|
||||||
self.PURPLE='\033[95m'
|
|
||||||
self.BLUE='\033[94m'
|
|
||||||
self.GREEN='\033[92m'
|
|
||||||
self.YELLOW='\033[93m'
|
|
||||||
self.RED='\033[91m'
|
|
||||||
self.BOLD='\033[1m'
|
|
||||||
self.UNDERLINE='\033[4m'
|
|
||||||
self.RESET="\x1B[m"
|
|
@ -19,13 +19,15 @@ and code to operate as a daemon, getting commands from the command queue databas
|
|||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
'''
|
'''
|
||||||
import sqlite3, requests, hmac, hashlib, time, sys, os, logger
|
import sqlite3, requests, hmac, hashlib, time, sys, os, logger, urllib.parse
|
||||||
import core, onionrutils
|
import core, onionrutils
|
||||||
|
|
||||||
class OnionrCommunicate:
|
class OnionrCommunicate:
|
||||||
def __init__(self, debug, developmentMode):
|
def __init__(self, debug, developmentMode):
|
||||||
''' OnionrCommunicate
|
'''
|
||||||
|
OnionrCommunicate
|
||||||
|
|
||||||
This class handles communication with nodes in the Onionr network.
|
This class handles communication with nodes in the Onionr network.
|
||||||
'''
|
'''
|
||||||
self._core = core.Core()
|
self._core = core.Core()
|
||||||
self._utils = onionrutils.OnionrUtils(self._core)
|
self._utils = onionrutils.OnionrUtils(self._core)
|
||||||
@ -63,29 +65,46 @@ class OnionrCommunicate:
|
|||||||
logger.warn('Daemon recieved exit command.')
|
logger.warn('Daemon recieved exit command.')
|
||||||
break
|
break
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
return
|
|
||||||
def getRemotePeerKey(self, peerID):
|
|
||||||
'''This function contacts a peer and gets their main PGP key.
|
|
||||||
|
|
||||||
This is safe because Tor or I2P is used, but it does not ensure that the person is who they say they are
|
return
|
||||||
|
|
||||||
|
def getRemotePeerKey(self, peerID):
|
||||||
|
'''
|
||||||
|
This function contacts a peer and gets their main PGP key.
|
||||||
|
|
||||||
|
This is safe because Tor or I2P is used, but it does not ensure that the person is who they say they are
|
||||||
'''
|
'''
|
||||||
url = 'http://' + peerID + '/public/?action=getPGP'
|
url = 'http://' + peerID + '/public/?action=getPGP'
|
||||||
r = requests.get(url, headers=headers)
|
r = requests.get(url, headers=headers)
|
||||||
response = r.text
|
response = r.text
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
def shareHMAC(self, peerID, key):
|
def shareHMAC(self, peerID, key):
|
||||||
'''This function shares an HMAC key to a peer
|
|
||||||
'''
|
'''
|
||||||
|
This function shares an HMAC key to a peer
|
||||||
|
'''
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def getPeerProof(self, peerID):
|
def getPeerProof(self, peerID):
|
||||||
'''This function gets the current peer proof requirement'''
|
'''
|
||||||
|
This function gets the current peer proof requirement
|
||||||
|
'''
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def sendPeerProof(self, peerID, data):
|
def sendPeerProof(self, peerID, data):
|
||||||
'''This function sends the proof result to a peer previously fetched with getPeerProof'''
|
'''
|
||||||
|
This function sends the proof result to a peer previously fetched with getPeerProof
|
||||||
|
'''
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def lookupBlocks(self):
|
def lookupBlocks(self):
|
||||||
'''Lookup blocks and merge new ones'''
|
'''
|
||||||
|
Lookup blocks and merge new ones
|
||||||
|
'''
|
||||||
peerList = self._core.listPeers()
|
peerList = self._core.listPeers()
|
||||||
blocks = ''
|
blocks = ''
|
||||||
for i in peerList:
|
for i in peerList:
|
||||||
@ -120,20 +139,26 @@ class OnionrCommunicate:
|
|||||||
else:
|
else:
|
||||||
logger.debug('Adding ' + i + ' to hash database...')
|
logger.debug('Adding ' + i + ' to hash database...')
|
||||||
self._core.addToBlockDB(i)
|
self._core.addToBlockDB(i)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def processBlocks(self):
|
def processBlocks(self):
|
||||||
'''
|
'''
|
||||||
Work with the block database and download any missing blocks
|
Work with the block database and download any missing blocks
|
||||||
This is meant to be called from the communicator daemon on its timer.
|
|
||||||
|
This is meant to be called from the communicator daemon on its timer.
|
||||||
'''
|
'''
|
||||||
for i in self._core.getBlockList(True).split("\n"):
|
for i in self._core.getBlockList(True).split("\n"):
|
||||||
if i != "":
|
if i != "":
|
||||||
logger.warn('UNSAVED BLOCK: ' + i)
|
logger.warn('UNSAVED BLOCK: ' + i)
|
||||||
data = self.downloadBlock(i)
|
data = self.downloadBlock(i)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def downloadBlock(self, hash):
|
def downloadBlock(self, hash):
|
||||||
'''download a block from random order of peers'''
|
'''
|
||||||
|
Download a block from random order of peers
|
||||||
|
'''
|
||||||
peerList = self._core.listPeers()
|
peerList = self._core.listPeers()
|
||||||
blocks = ''
|
blocks = ''
|
||||||
for i in peerList:
|
for i in peerList:
|
||||||
@ -155,22 +180,33 @@ class OnionrCommunicate:
|
|||||||
else:
|
else:
|
||||||
logger.warn("Failed to validate " + hash)
|
logger.warn("Failed to validate " + hash)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def urlencode(self, data):
|
||||||
|
'''
|
||||||
|
URL encodes the data
|
||||||
|
'''
|
||||||
|
return urllib.parse.quote_plus(data)
|
||||||
|
|
||||||
def performGet(self, action, peer, data=None, type='tor'):
|
def performGet(self, action, peer, data=None, type='tor'):
|
||||||
'''Performs a request to a peer through Tor or i2p (currently only tor)'''
|
'''
|
||||||
|
Performs a request to a peer through Tor or i2p (currently only Tor)
|
||||||
|
'''
|
||||||
if not peer.endswith('.onion') and not peer.endswith('.onion/'):
|
if not peer.endswith('.onion') and not peer.endswith('.onion/'):
|
||||||
raise PeerError('Currently only Tor .onion peers are supported. You must manually specify .onion')
|
raise PeerError('Currently only Tor .onion peers are supported. You must manually specify .onion')
|
||||||
socksPort = sys.argv[2]
|
socksPort = sys.argv[2]
|
||||||
'''We use socks5h to use tor as DNS'''
|
'''We use socks5h to use tor as DNS'''
|
||||||
proxies = {'http': 'socks5h://127.0.0.1:' + str(socksPort), 'https': 'socks5h://127.0.0.1:' + str(socksPort)}
|
proxies = {'http': 'socks5h://127.0.0.1:' + str(socksPort), 'https': 'socks5h://127.0.0.1:' + str(socksPort)}
|
||||||
headers = {'user-agent': 'PyOnionr'}
|
headers = {'user-agent': 'PyOnionr'}
|
||||||
url = 'http://' + peer + '/public/?action=' + action
|
url = 'http://' + peer + '/public/?action=' + urlencode(action)
|
||||||
if data != None:
|
if data != None:
|
||||||
url = url + '&data=' + data
|
url = url + '&data=' + urlencode(data)
|
||||||
try:
|
try:
|
||||||
r = requests.get(url, headers=headers, proxies=proxies, timeout=(15, 30))
|
r = requests.get(url, headers=headers, proxies=proxies, timeout=(15, 30))
|
||||||
except requests.exceptions.RequestException as e:
|
except requests.exceptions.RequestException as e:
|
||||||
logger.warn(action + " failed with peer " + peer + ": " + str(e))
|
logger.warn(action + " failed with peer " + peer + ": " + str(e))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return r.text
|
return r.text
|
||||||
|
|
||||||
|
|
||||||
|
190
onionr/core.py
190
onionr/core.py
@ -34,7 +34,7 @@ if sys.version_info < (3, 6):
|
|||||||
class Core:
|
class Core:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
'''
|
'''
|
||||||
Initialize Core Onionr library
|
Initialize Core Onionr library
|
||||||
'''
|
'''
|
||||||
self.queueDB = 'data/queue.db'
|
self.queueDB = 'data/queue.db'
|
||||||
self.peerDB = 'data/peers.db'
|
self.peerDB = 'data/peers.db'
|
||||||
@ -54,87 +54,101 @@ class Core:
|
|||||||
return
|
return
|
||||||
|
|
||||||
def generateMainPGP(self, myID):
|
def generateMainPGP(self, myID):
|
||||||
''' Generate the main PGP key for our client. Should not be done often.
|
'''
|
||||||
Uses own PGP home folder in the data/ directory. '''
|
Generate the main PGP key for our client. Should not be done often.
|
||||||
# Generate main pgp key
|
|
||||||
|
Uses own PGP home folder in the data/ directory
|
||||||
|
'''
|
||||||
gpg = gnupg.GPG(homedir='./data/pgp/')
|
gpg = gnupg.GPG(homedir='./data/pgp/')
|
||||||
input_data = gpg.gen_key_input(key_type="RSA", key_length=1024, name_real=myID, name_email='anon@onionr', testing=True)
|
input_data = gpg.gen_key_input(key_type="RSA", key_length=1024, name_real=myID, name_email='anon@onionr', testing=True)
|
||||||
#input_data = gpg.gen_key_input(key_type="RSA", key_length=1024)
|
|
||||||
key = gpg.gen_key(input_data)
|
key = gpg.gen_key(input_data)
|
||||||
logger.info("Generating PGP key, this will take some time..")
|
logger.info("Generating PGP key, this will take some time..")
|
||||||
while key.status != "key created":
|
while key.status != "key created":
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
print(key.status)
|
print(key.status)
|
||||||
|
|
||||||
logger.info("Finished generating PGP key")
|
logger.info("Finished generating PGP key")
|
||||||
# Write the key
|
# Write the key
|
||||||
myFingerpintFile = open('data/own-fingerprint.txt', 'w')
|
myFingerpintFile = open('data/own-fingerprint.txt', 'w')
|
||||||
myFingerpintFile.write(key.fingerprint)
|
myFingerpintFile.write(key.fingerprint)
|
||||||
myFingerpintFile.close()
|
myFingerpintFile.close()
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def addPeer(self, peerID, name=''):
|
def addPeer(self, peerID, name=''):
|
||||||
''' Add a peer by their ID, with an optional name, to the peer database.'''
|
'''
|
||||||
''' DOES NO SAFETY CHECKS if the ID is valid, but prepares the insertion. '''
|
Add a peer by their ID, with an optional name, to the peer database
|
||||||
|
|
||||||
|
DOES NO SAFETY CHECKS if the ID is valid, but prepares the insertion
|
||||||
|
'''
|
||||||
# This function simply adds a peer to the DB
|
# This function simply adds a peer to the DB
|
||||||
if not self._utils.validateID(peerID):
|
if not self._utils.validateID(peerID):
|
||||||
return False
|
return False
|
||||||
conn = sqlite3.connect(self.peerDB)
|
conn = sqlite3.connect(self.peerDB)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
t = (peerID, name, 'unknown')
|
t = (peerID, name, 'unknown')
|
||||||
c.execute('insert into peers (id, name, dateSeen) values(?, ?, ?);', t)
|
c.execute('INSERT INTO peers (id, name, dateSeen) VALUES(?, ?, ?);', t)
|
||||||
conn.commit()
|
conn.commit()
|
||||||
conn.close()
|
conn.close()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def createPeerDB(self):
|
def createPeerDB(self):
|
||||||
'''
|
'''
|
||||||
Generate the peer sqlite3 database and populate it with the peers table.
|
Generate the peer sqlite3 database and populate it with the peers table.
|
||||||
'''
|
'''
|
||||||
# generate the peer database
|
# generate the peer database
|
||||||
conn = sqlite3.connect(self.peerDB)
|
conn = sqlite3.connect(self.peerDB)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
c.execute('''
|
c.execute('''CREATE TABLE peers(
|
||||||
create table peers(
|
ID text not null,
|
||||||
ID text not null,
|
name text,
|
||||||
name text,
|
pgpKey text,
|
||||||
pgpKey text,
|
hmacKey text,
|
||||||
hmacKey text,
|
blockDBHash text,
|
||||||
blockDBHash text,
|
forwardKey text,
|
||||||
forwardKey text,
|
dateSeen not null,
|
||||||
dateSeen not null,
|
bytesStored int,
|
||||||
bytesStored int,
|
trust int);
|
||||||
trust int);
|
|
||||||
''')
|
''')
|
||||||
conn.commit()
|
conn.commit()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
def createBlockDB(self):
|
def createBlockDB(self):
|
||||||
'''
|
'''
|
||||||
Create a database for blocks
|
Create a database for blocks
|
||||||
|
|
||||||
hash - the hash of a block
|
hash - the hash of a block
|
||||||
dateReceived - the date the block was recieved, not necessarily when it was created
|
dateReceived - the date the block was recieved, not necessarily when it was created
|
||||||
decrypted - if we can successfully decrypt the block (does not describe its current state)
|
decrypted - if we can successfully decrypt the block (does not describe its current state)
|
||||||
dataType - data type of the block
|
dataType - data type of the block
|
||||||
dataFound - if the data has been found for the block
|
dataFound - if the data has been found for the block
|
||||||
dataSaved - if the data has been saved for the block
|
dataSaved - if the data has been saved for the block
|
||||||
'''
|
'''
|
||||||
if os.path.exists(self.blockDB):
|
if os.path.exists(self.blockDB):
|
||||||
raise Exception("Block database already exists")
|
raise Exception("Block database already exists")
|
||||||
conn = sqlite3.connect(self.blockDB)
|
conn = sqlite3.connect(self.blockDB)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
c.execute('''create table hashes(
|
c.execute('''CREATE TABLE hashes(
|
||||||
hash text not null,
|
hash text not null,
|
||||||
dateReceived int,
|
dateReceived int,
|
||||||
decrypted int,
|
decrypted int,
|
||||||
dataType text,
|
dataType text,
|
||||||
dataFound int,
|
dataFound int,
|
||||||
dataSaved int
|
dataSaved int);
|
||||||
);
|
|
||||||
''')
|
''')
|
||||||
conn.commit()
|
conn.commit()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
def addToBlockDB(self, newHash, selfInsert=False):
|
def addToBlockDB(self, newHash, selfInsert=False):
|
||||||
'''add a hash value to the block db (should be in hex format)'''
|
'''
|
||||||
|
Add a hash value to the block db
|
||||||
|
|
||||||
|
Should be in hex format!
|
||||||
|
'''
|
||||||
if not os.path.exists(self.blockDB):
|
if not os.path.exists(self.blockDB):
|
||||||
raise Exception('Block db does not exist')
|
raise Exception('Block db does not exist')
|
||||||
if self._utils.hasBlock(newHash):
|
if self._utils.hasBlock(newHash):
|
||||||
@ -147,22 +161,29 @@ class Core:
|
|||||||
else:
|
else:
|
||||||
selfInsert = 0
|
selfInsert = 0
|
||||||
data = (newHash, currentTime, 0, '', 0, selfInsert)
|
data = (newHash, currentTime, 0, '', 0, selfInsert)
|
||||||
c.execute('INSERT into hashes values(?, ?, ?, ?, ?, ?);', data)
|
c.execute('INSERT INTO hashes VALUES(?, ?, ?, ?, ?, ?);', data)
|
||||||
conn.commit()
|
conn.commit()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
def getData(self,hash):
|
def getData(self,hash):
|
||||||
'''simply return the data associated to a hash'''
|
'''
|
||||||
|
Simply return the data associated to a hash
|
||||||
|
'''
|
||||||
try:
|
try:
|
||||||
dataFile = open(self.blockDataLocation + hash + '.dat')
|
dataFile = open(self.blockDataLocation + hash + '.dat')
|
||||||
data = dataFile.read()
|
data = dataFile.read()
|
||||||
dataFile.close()
|
dataFile.close()
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
data = False
|
data = False
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def setData(self, data):
|
def setData(self, data):
|
||||||
'''set the data assciated with a hash'''
|
'''
|
||||||
|
Set the data assciated with a hash
|
||||||
|
'''
|
||||||
data = data.encode()
|
data = data.encode()
|
||||||
hasher = hashlib.sha3_256()
|
hasher = hashlib.sha3_256()
|
||||||
hasher.update(data)
|
hasher.update(data)
|
||||||
@ -171,7 +192,7 @@ class Core:
|
|||||||
dataHash = dataHash.decode()
|
dataHash = dataHash.decode()
|
||||||
blockFileName = self.blockDataLocation + dataHash + '.dat'
|
blockFileName = self.blockDataLocation + dataHash + '.dat'
|
||||||
if os.path.exists(blockFileName):
|
if os.path.exists(blockFileName):
|
||||||
pass # to do, properly check if block is already saved elsewhere
|
pass # TODO: properly check if block is already saved elsewhere
|
||||||
#raise Exception("Data is already set for " + dataHash)
|
#raise Exception("Data is already set for " + dataHash)
|
||||||
else:
|
else:
|
||||||
blockFile = open(blockFileName, 'w')
|
blockFile = open(blockFileName, 'w')
|
||||||
@ -180,7 +201,7 @@ class Core:
|
|||||||
|
|
||||||
conn = sqlite3.connect(self.blockDB)
|
conn = sqlite3.connect(self.blockDB)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
c.execute("UPDATE hashes set dataSaved=1 where hash = '" + dataHash + "';")
|
c.execute("UPDATE hashes SET dataSaved=1 WHERE hash = '" + dataHash + "';")
|
||||||
conn.commit()
|
conn.commit()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
@ -188,9 +209,8 @@ class Core:
|
|||||||
|
|
||||||
def dataDirEncrypt(self, password):
|
def dataDirEncrypt(self, password):
|
||||||
'''
|
'''
|
||||||
Encrypt the data directory on Onionr shutdown
|
Encrypt the data directory on Onionr shutdown
|
||||||
'''
|
'''
|
||||||
# Encrypt data directory (don't delete it in this function)
|
|
||||||
if os.path.exists('data.tar'):
|
if os.path.exists('data.tar'):
|
||||||
os.remove('data.tar')
|
os.remove('data.tar')
|
||||||
tar = tarfile.open("data.tar", "w")
|
tar = tarfile.open("data.tar", "w")
|
||||||
@ -201,12 +221,13 @@ class Core:
|
|||||||
encrypted = simplecrypt.encrypt(password, tarData)
|
encrypted = simplecrypt.encrypt(password, tarData)
|
||||||
open('data-encrypted.dat', 'wb').write(encrypted)
|
open('data-encrypted.dat', 'wb').write(encrypted)
|
||||||
os.remove('data.tar')
|
os.remove('data.tar')
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def dataDirDecrypt(self, password):
|
def dataDirDecrypt(self, password):
|
||||||
'''
|
'''
|
||||||
Decrypt the data directory on startup
|
Decrypt the data directory on startup
|
||||||
'''
|
'''
|
||||||
# Decrypt data directory
|
|
||||||
if not os.path.exists('data-encrypted.dat'):
|
if not os.path.exists('data-encrypted.dat'):
|
||||||
return (False, 'encrypted archive does not exist')
|
return (False, 'encrypted archive does not exist')
|
||||||
data = open('data-encrypted.dat', 'rb').read()
|
data = open('data-encrypted.dat', 'rb').read()
|
||||||
@ -219,13 +240,15 @@ class Core:
|
|||||||
tar = tarfile.open('data.tar')
|
tar = tarfile.open('data.tar')
|
||||||
tar.extractall()
|
tar.extractall()
|
||||||
tar.close()
|
tar.close()
|
||||||
|
|
||||||
return (True, '')
|
return (True, '')
|
||||||
|
|
||||||
def daemonQueue(self):
|
def daemonQueue(self):
|
||||||
'''
|
'''
|
||||||
Gives commands to the communication proccess/daemon by reading an sqlite3 database
|
Gives commands to the communication proccess/daemon by reading an sqlite3 database
|
||||||
|
|
||||||
|
This function intended to be used by the client. Queue to exchange data between "client" and server.
|
||||||
'''
|
'''
|
||||||
# This function intended to be used by the client
|
|
||||||
# Queue to exchange data between "client" and server.
|
|
||||||
retData = False
|
retData = False
|
||||||
if not os.path.exists(self.queueDB):
|
if not os.path.exists(self.queueDB):
|
||||||
conn = sqlite3.connect(self.queueDB)
|
conn = sqlite3.connect(self.queueDB)
|
||||||
@ -241,7 +264,7 @@ class Core:
|
|||||||
retData = row
|
retData = row
|
||||||
break
|
break
|
||||||
if retData != False:
|
if retData != False:
|
||||||
c.execute('delete from commands where id = ?', (retData[3],))
|
c.execute('DELETE FROM commands WHERE id=?;', (retData[3],))
|
||||||
conn.commit()
|
conn.commit()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
@ -249,19 +272,23 @@ class Core:
|
|||||||
|
|
||||||
def daemonQueueAdd(self, command, data=''):
|
def daemonQueueAdd(self, command, data=''):
|
||||||
'''
|
'''
|
||||||
Add a command to the daemon queue, used by the communication daemon (communicator.py)
|
Add a command to the daemon queue, used by the communication daemon (communicator.py)
|
||||||
'''
|
'''
|
||||||
# Intended to be used by the web server
|
# Intended to be used by the web server
|
||||||
date = math.floor(time.time())
|
date = math.floor(time.time())
|
||||||
conn = sqlite3.connect(self.queueDB)
|
conn = sqlite3.connect(self.queueDB)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
t = (command, data, date)
|
t = (command, data, date)
|
||||||
c.execute('INSERT into commands (command, data, date) values (?, ?, ?)', t)
|
c.execute('INSERT INTO commands (command, data, date) VALUES(?, ?, ?)', t)
|
||||||
conn.commit()
|
conn.commit()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def clearDaemonQueue(self):
|
def clearDaemonQueue(self):
|
||||||
'''clear the daemon queue (somewhat dangerousous)'''
|
'''
|
||||||
|
Clear the daemon queue (somewhat dangerous)
|
||||||
|
'''
|
||||||
conn = sqlite3.connect(self.queueDB)
|
conn = sqlite3.connect(self.queueDB)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
try:
|
try:
|
||||||
@ -271,45 +298,49 @@ class Core:
|
|||||||
pass
|
pass
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
def generateHMAC(self):
|
return
|
||||||
|
|
||||||
|
def generateHMAC(self, length=32):
|
||||||
'''
|
'''
|
||||||
generate and return an HMAC key
|
Generate and return an HMAC key
|
||||||
'''
|
'''
|
||||||
key = base64.b64encode(os.urandom(32))
|
key = base64.b64encode(os.urandom(length))
|
||||||
|
|
||||||
return key
|
return key
|
||||||
|
|
||||||
def listPeers(self, randomOrder=True):
|
def listPeers(self, randomOrder=True):
|
||||||
'''Return a list of peers
|
'''
|
||||||
|
Return a list of peers
|
||||||
|
|
||||||
randomOrder determines if the list should be in a random order
|
randomOrder determines if the list should be in a random order
|
||||||
'''
|
'''
|
||||||
conn = sqlite3.connect(self.peerDB)
|
conn = sqlite3.connect(self.peerDB)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
if randomOrder:
|
if randomOrder:
|
||||||
peers = c.execute('SELECT * FROM peers order by RANDOM();')
|
peers = c.execute('SELECT * FROM peers ORDER BY RANDOM();')
|
||||||
else:
|
else:
|
||||||
peers = c.execute('SELECT * FROM peers;')
|
peers = c.execute('SELECT * FROM peers;')
|
||||||
peerList = []
|
peerList = []
|
||||||
for i in peers:
|
for i in peers:
|
||||||
peerList.append(i[0])
|
peerList.append(i[0])
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
return peerList
|
return peerList
|
||||||
|
|
||||||
def getPeerInfo(self, peer, info):
|
def getPeerInfo(self, peer, info):
|
||||||
'''
|
'''
|
||||||
get info about a peer
|
Get info about a peer from their database entry
|
||||||
|
|
||||||
id text 0
|
id text 0
|
||||||
name text, 1
|
name text, 1
|
||||||
pgpKey text, 2
|
pgpKey text, 2
|
||||||
hmacKey text, 3
|
hmacKey text, 3
|
||||||
blockDBHash text, 4
|
blockDBHash text, 4
|
||||||
forwardKey text, 5
|
forwardKey text, 5
|
||||||
dateSeen not null, 7
|
dateSeen not null, 7
|
||||||
bytesStored int, 8
|
bytesStored int, 8
|
||||||
trust int 9
|
trust int 9
|
||||||
'''
|
'''
|
||||||
# Lookup something about a peer from their database entry
|
|
||||||
conn = sqlite3.connect(self.peerDB)
|
conn = sqlite3.connect(self.peerDB)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
command = (peer,)
|
command = (peer,)
|
||||||
@ -325,21 +356,29 @@ class Core:
|
|||||||
else:
|
else:
|
||||||
iterCount += 1
|
iterCount += 1
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
return retVal
|
return retVal
|
||||||
|
|
||||||
def setPeerInfo(self, peer, key, data):
|
def setPeerInfo(self, peer, key, data):
|
||||||
'''update a peer for a key'''
|
'''
|
||||||
|
Update a peer for a key
|
||||||
|
'''
|
||||||
conn = sqlite3.connect(self.peerDB)
|
conn = sqlite3.connect(self.peerDB)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
command = (data, peer)
|
command = (data, peer)
|
||||||
# TODO: validate key on whitelist
|
# TODO: validate key on whitelist
|
||||||
if key not in ('id', 'text', 'name', 'pgpKey', 'hmacKey', 'blockDBHash', 'forwardKey', 'dateSeen', 'bytesStored', 'trust'):
|
if key not in ('id', 'text', 'name', 'pgpKey', 'hmacKey', 'blockDBHash', 'forwardKey', 'dateSeen', 'bytesStored', 'trust'):
|
||||||
raise Exception("Got invalid database key when setting peer info")
|
raise Exception("Got invalid database key when setting peer info")
|
||||||
c.execute('UPDATE peers SET ' + key + ' = ? where id=?', command)
|
c.execute('UPDATE peers SET ' + key + ' = ? WHERE id=?', command)
|
||||||
conn.commit()
|
conn.commit()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
def getBlockList(self, unsaved=False):
|
def getBlockList(self, unsaved=False):
|
||||||
'''get list of our blocks'''
|
'''
|
||||||
|
Get list of our blocks
|
||||||
|
'''
|
||||||
conn = sqlite3.connect(self.blockDB)
|
conn = sqlite3.connect(self.blockDB)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
retData = ''
|
retData = ''
|
||||||
@ -350,24 +389,33 @@ class Core:
|
|||||||
for row in c.execute(execute):
|
for row in c.execute(execute):
|
||||||
for i in row:
|
for i in row:
|
||||||
retData += i + "\n"
|
retData += i + "\n"
|
||||||
|
|
||||||
return retData
|
return retData
|
||||||
|
|
||||||
def getBlocksByType(self, blockType):
|
def getBlocksByType(self, blockType):
|
||||||
|
'''
|
||||||
|
Returns a list of blocks by the type
|
||||||
|
'''
|
||||||
conn = sqlite3.connect(self.blockDB)
|
conn = sqlite3.connect(self.blockDB)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
retData = ''
|
retData = ''
|
||||||
execute = 'SELECT hash FROM hashes where dataType=?'
|
execute = 'SELECT hash FROM hashes WHERE dataType=?;'
|
||||||
args = (blockType,)
|
args = (blockType,)
|
||||||
for row in c.execute(execute, args):
|
for row in c.execute(execute, args):
|
||||||
for i in row:
|
for i in row:
|
||||||
retData += i + "\n"
|
retData += i + "\n"
|
||||||
|
|
||||||
return retData.split('\n')
|
return retData.split('\n')
|
||||||
|
|
||||||
def setBlockType(self, hash, blockType):
|
def setBlockType(self, hash, blockType):
|
||||||
|
'''
|
||||||
|
Sets the type of block
|
||||||
|
'''
|
||||||
|
|
||||||
conn = sqlite3.connect(self.blockDB)
|
conn = sqlite3.connect(self.blockDB)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
#if blockType not in ("txt"):
|
|
||||||
# return
|
|
||||||
c.execute("UPDATE hashes SET dataType='" + blockType + "' WHERE hash = '" + hash + "';")
|
c.execute("UPDATE hashes SET dataType='" + blockType + "' WHERE hash = '" + hash + "';")
|
||||||
conn.commit()
|
conn.commit()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
|
return
|
||||||
|
@ -19,8 +19,8 @@
|
|||||||
'''
|
'''
|
||||||
import subprocess, os, random, sys, logger, time, signal
|
import subprocess, os, random, sys, logger, time, signal
|
||||||
class NetController:
|
class NetController:
|
||||||
'''NetController
|
'''
|
||||||
This class handles hidden service setup on Tor and I2P
|
This class handles hidden service setup on Tor and I2P
|
||||||
'''
|
'''
|
||||||
def __init__(self, hsPort):
|
def __init__(self, hsPort):
|
||||||
self.torConfigLocation = 'data/torrc'
|
self.torConfigLocation = 'data/torrc'
|
||||||
@ -30,15 +30,19 @@ class NetController:
|
|||||||
self._torInstnace = ''
|
self._torInstnace = ''
|
||||||
self.myID = ''
|
self.myID = ''
|
||||||
'''
|
'''
|
||||||
if os.path.exists(self.torConfigLocation):
|
if os.path.exists(self.torConfigLocation):
|
||||||
torrc = open(self.torConfigLocation, 'r')
|
torrc = open(self.torConfigLocation, 'r')
|
||||||
if not str(self.hsPort) in torrc.read():
|
if not str(self.hsPort) in torrc.read():
|
||||||
os.remove(self.torConfigLocation)
|
os.remove(self.torConfigLocation)
|
||||||
torrc.close()
|
torrc.close()
|
||||||
'''
|
'''
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def generateTorrc(self):
|
def generateTorrc(self):
|
||||||
'''generate a torrc file for our tor instance'''
|
'''
|
||||||
|
Generate a torrc file for our tor instance
|
||||||
|
'''
|
||||||
if os.path.exists(self.torConfigLocation):
|
if os.path.exists(self.torConfigLocation):
|
||||||
os.remove(self.torConfigLocation)
|
os.remove(self.torConfigLocation)
|
||||||
torrcData = '''SocksPort ''' + str(self.socksPort) + '''
|
torrcData = '''SocksPort ''' + str(self.socksPort) + '''
|
||||||
@ -48,10 +52,12 @@ HiddenServicePort 80 127.0.0.1:''' + str(self.hsPort) + '''
|
|||||||
torrc = open(self.torConfigLocation, 'w')
|
torrc = open(self.torConfigLocation, 'w')
|
||||||
torrc.write(torrcData)
|
torrc.write(torrcData)
|
||||||
torrc.close()
|
torrc.close()
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def startTor(self):
|
def startTor(self):
|
||||||
'''Start Tor with onion service on port 80 & socks proxy on random port
|
'''
|
||||||
|
Start Tor with onion service on port 80 & socks proxy on random port
|
||||||
'''
|
'''
|
||||||
self.generateTorrc()
|
self.generateTorrc()
|
||||||
if os.path.exists('./tor'):
|
if os.path.exists('./tor'):
|
||||||
@ -80,9 +86,13 @@ HiddenServicePort 80 127.0.0.1:''' + str(self.hsPort) + '''
|
|||||||
torPidFile = open('data/torPid.txt', 'w')
|
torPidFile = open('data/torPid.txt', 'w')
|
||||||
torPidFile.write(str(tor.pid))
|
torPidFile.write(str(tor.pid))
|
||||||
torPidFile.close()
|
torPidFile.close()
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def killTor(self):
|
def killTor(self):
|
||||||
'''properly kill tor based on pid saved to file'''
|
'''
|
||||||
|
Properly kill tor based on pid saved to file
|
||||||
|
'''
|
||||||
try:
|
try:
|
||||||
pid = open('data/torPid.txt', 'r')
|
pid = open('data/torPid.txt', 'r')
|
||||||
pidN = pid.read()
|
pidN = pid.read()
|
||||||
@ -95,3 +105,5 @@ HiddenServicePort 80 127.0.0.1:''' + str(self.hsPort) + '''
|
|||||||
return
|
return
|
||||||
os.kill(int(pidN), signal.SIGTERM)
|
os.kill(int(pidN), signal.SIGTERM)
|
||||||
os.remove('data/torPid.txt')
|
os.remove('data/torPid.txt')
|
||||||
|
|
||||||
|
return
|
||||||
|
@ -234,4 +234,3 @@ class Onionr:
|
|||||||
return
|
return
|
||||||
|
|
||||||
Onionr()
|
Onionr()
|
||||||
|
|
||||||
|
@ -22,9 +22,12 @@ import nacl
|
|||||||
class OnionrCrypto:
|
class OnionrCrypto:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
return
|
return
|
||||||
|
|
||||||
def symmetricPeerEncrypt(self, data, key):
|
def symmetricPeerEncrypt(self, data, key):
|
||||||
return
|
return
|
||||||
|
|
||||||
def symmetricPeerDecrypt(self, data, key):
|
def symmetricPeerDecrypt(self, data, key):
|
||||||
return
|
return
|
||||||
|
|
||||||
def rsaEncrypt(self, peer, data):
|
def rsaEncrypt(self, peer, data):
|
||||||
return
|
return
|
||||||
|
@ -32,15 +32,22 @@ class OnionrUtils:
|
|||||||
self._core = coreInstance
|
self._core = coreInstance
|
||||||
return
|
return
|
||||||
def localCommand(self, command):
|
def localCommand(self, command):
|
||||||
'''Send a command to the local http API server, securely. Intended for local clients, DO NOT USE for remote peers.'''
|
'''
|
||||||
|
Send a command to the local http API server, securely. Intended for local clients, DO NOT USE for remote peers.
|
||||||
|
'''
|
||||||
config = configparser.ConfigParser()
|
config = configparser.ConfigParser()
|
||||||
if os.path.exists('data/config.ini'):
|
if os.path.exists('data/config.ini'):
|
||||||
config.read('data/config.ini')
|
config.read('data/config.ini')
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
requests.get('http://' + open('data/host.txt', 'r').read() + ':' + str(config['CLIENT']['PORT']) + '/client/?action=' + command + '&token=' + config['CLIENT']['CLIENT HMAC'])
|
requests.get('http://' + open('data/host.txt', 'r').read() + ':' + str(config['CLIENT']['PORT']) + '/client/?action=' + command + '&token=' + config['CLIENT']['CLIENT HMAC'])
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
def getPassword(self, message='Enter password: ', confirm = True):
|
def getPassword(self, message='Enter password: ', confirm = True):
|
||||||
'''Get a password without showing the users typing and confirm the input'''
|
'''
|
||||||
|
Get a password without showing the users typing and confirm the input
|
||||||
|
'''
|
||||||
# Get a password safely with confirmation and return it
|
# Get a password safely with confirmation and return it
|
||||||
while True:
|
while True:
|
||||||
print(message)
|
print(message)
|
||||||
@ -55,9 +62,13 @@ class OnionrUtils:
|
|||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
|
|
||||||
return pass1
|
return pass1
|
||||||
def checkPort(self, port, host = ''):
|
|
||||||
'''Checks if a port is available, returns bool'''
|
def checkPort(self, port, host=''):
|
||||||
|
'''
|
||||||
|
Checks if a port is available, returns bool
|
||||||
|
'''
|
||||||
# inspired by https://www.reddit.com/r/learnpython/comments/2i4qrj/how_to_write_a_python_script_that_checks_to_see/ckzarux/
|
# inspired by https://www.reddit.com/r/learnpython/comments/2i4qrj/how_to_write_a_python_script_that_checks_to_see/ckzarux/
|
||||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
retVal = False
|
retVal = False
|
||||||
@ -68,36 +79,49 @@ class OnionrUtils:
|
|||||||
retVal = True
|
retVal = True
|
||||||
finally:
|
finally:
|
||||||
sock.close()
|
sock.close()
|
||||||
|
|
||||||
return retVal
|
return retVal
|
||||||
|
|
||||||
def checkIsIP(self, ip):
|
def checkIsIP(self, ip):
|
||||||
'''Check if a string is a valid ipv4 address'''
|
'''
|
||||||
|
Check if a string is a valid IPv4 address
|
||||||
|
'''
|
||||||
try:
|
try:
|
||||||
socket.inet_aton(ip)
|
socket.inet_aton(ip)
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def exportMyPubkey(self):
|
def exportMyPubkey(self):
|
||||||
'''Export our PGP key if it exists'''
|
'''
|
||||||
|
Export our PGP key if it exists
|
||||||
|
'''
|
||||||
if not os.path.exists(self.fingerprintFile):
|
if not os.path.exists(self.fingerprintFile):
|
||||||
raise Exception("No fingerprint found, cannot export our PGP key.")
|
raise Exception("No fingerprint found, cannot export our PGP key.")
|
||||||
gpg = gnupg.GPG(homedir='./data/pgp/')
|
gpg = gnupg.GPG(homedir='./data/pgp/')
|
||||||
with open(self.fingerprintFile,'r') as f:
|
with open(self.fingerprintFile,'r') as f:
|
||||||
fingerprint = f.read()
|
fingerprint = f.read()
|
||||||
ascii_armored_public_keys = gpg.export_keys(fingerprint)
|
ascii_armored_public_keys = gpg.export_keys(fingerprint)
|
||||||
|
|
||||||
return ascii_armored_public_keys
|
return ascii_armored_public_keys
|
||||||
|
|
||||||
def getBlockDBHash(self):
|
def getBlockDBHash(self):
|
||||||
'''Return a sha3_256 hash of the blocks DB'''
|
'''
|
||||||
|
Return a sha3_256 hash of the blocks DB
|
||||||
|
'''
|
||||||
with open(self._core.blockDB, 'rb') as data:
|
with open(self._core.blockDB, 'rb') as data:
|
||||||
data = data.read()
|
data = data.read()
|
||||||
hasher = hashlib.sha3_256()
|
hasher = hashlib.sha3_256()
|
||||||
hasher.update(data)
|
hasher.update(data)
|
||||||
dataHash = hasher.hexdigest()
|
dataHash = hasher.hexdigest()
|
||||||
|
|
||||||
return dataHash
|
return dataHash
|
||||||
|
|
||||||
def hasBlock(self, hash):
|
def hasBlock(self, hash):
|
||||||
'''detect if we have a block in the list or not'''
|
'''
|
||||||
|
Check for new block in the list
|
||||||
|
'''
|
||||||
conn = sqlite3.connect(self._core.blockDB)
|
conn = sqlite3.connect(self._core.blockDB)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
if not self.validateHash(hash):
|
if not self.validateHash(hash):
|
||||||
@ -113,7 +137,9 @@ class OnionrUtils:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def validateHash(self, data, length=64):
|
def validateHash(self, data, length=64):
|
||||||
'''Validate if a string is a valid hex formatted hash'''
|
'''
|
||||||
|
Validate if a string is a valid hex formatted hash
|
||||||
|
'''
|
||||||
retVal = True
|
retVal = True
|
||||||
if data == False or data == True:
|
if data == False or data == True:
|
||||||
return False
|
return False
|
||||||
@ -125,9 +151,13 @@ class OnionrUtils:
|
|||||||
int(data, 16)
|
int(data, 16)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
retVal = False
|
retVal = False
|
||||||
|
|
||||||
return retVal
|
return retVal
|
||||||
|
|
||||||
def validateID(self, id):
|
def validateID(self, id):
|
||||||
'''validate if a user ID is a valid tor or i2p hidden service'''
|
'''
|
||||||
|
Validate if a user ID is a valid tor or i2p hidden service
|
||||||
|
'''
|
||||||
idLength = len(id)
|
idLength = len(id)
|
||||||
retVal = True
|
retVal = True
|
||||||
idNoDomain = ''
|
idNoDomain = ''
|
||||||
@ -165,4 +195,5 @@ class OnionrUtils:
|
|||||||
retVal = False
|
retVal = False
|
||||||
if not idNoDomain.isalnum():
|
if not idNoDomain.isalnum():
|
||||||
retVal = False
|
retVal = False
|
||||||
|
|
||||||
return retVal
|
return retVal
|
||||||
|
@ -23,6 +23,7 @@ class OnionrTests(unittest.TestCase):
|
|||||||
self.assertTrue(False)
|
self.assertTrue(False)
|
||||||
else:
|
else:
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
|
|
||||||
def testNone(self):
|
def testNone(self):
|
||||||
logger.debug('--------------------------')
|
logger.debug('--------------------------')
|
||||||
logger.info('Running simple program run test...')
|
logger.info('Running simple program run test...')
|
||||||
@ -32,6 +33,7 @@ class OnionrTests(unittest.TestCase):
|
|||||||
self.assertTrue(False)
|
self.assertTrue(False)
|
||||||
else:
|
else:
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
|
|
||||||
def testPeer_a_DBCreation(self):
|
def testPeer_a_DBCreation(self):
|
||||||
logger.debug('--------------------------')
|
logger.debug('--------------------------')
|
||||||
logger.info('Running peer db creation test...')
|
logger.info('Running peer db creation test...')
|
||||||
@ -44,6 +46,7 @@ class OnionrTests(unittest.TestCase):
|
|||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
else:
|
else:
|
||||||
self.assertTrue(False)
|
self.assertTrue(False)
|
||||||
|
|
||||||
def testPeer_b_addPeerToDB(self):
|
def testPeer_b_addPeerToDB(self):
|
||||||
logger.debug('--------------------------')
|
logger.debug('--------------------------')
|
||||||
logger.info('Running peer db insertion test...')
|
logger.info('Running peer db insertion test...')
|
||||||
@ -55,6 +58,7 @@ class OnionrTests(unittest.TestCase):
|
|||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
else:
|
else:
|
||||||
self.assertTrue(False)
|
self.assertTrue(False)
|
||||||
|
|
||||||
def testData_b_Encrypt(self):
|
def testData_b_Encrypt(self):
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
return
|
return
|
||||||
@ -67,6 +71,7 @@ class OnionrTests(unittest.TestCase):
|
|||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
else:
|
else:
|
||||||
self.assertTrue(False)
|
self.assertTrue(False)
|
||||||
|
|
||||||
def testData_a_Decrypt(self):
|
def testData_a_Decrypt(self):
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
return
|
return
|
||||||
@ -79,6 +84,7 @@ class OnionrTests(unittest.TestCase):
|
|||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
else:
|
else:
|
||||||
self.assertTrue(False)
|
self.assertTrue(False)
|
||||||
|
|
||||||
def testPGPGen(self):
|
def testPGPGen(self):
|
||||||
logger.debug('--------------------------')
|
logger.debug('--------------------------')
|
||||||
logger.info('Running PGP key generation test...')
|
logger.info('Running PGP key generation test...')
|
||||||
@ -93,6 +99,7 @@ class OnionrTests(unittest.TestCase):
|
|||||||
myCore.generateMainPGP(torID)
|
myCore.generateMainPGP(torID)
|
||||||
if os.path.exists('data/pgp/'):
|
if os.path.exists('data/pgp/'):
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
|
|
||||||
def testHMACGen(self):
|
def testHMACGen(self):
|
||||||
logger.debug('--------------------------')
|
logger.debug('--------------------------')
|
||||||
logger.info('Running HMAC generation test...')
|
logger.info('Running HMAC generation test...')
|
||||||
@ -104,6 +111,7 @@ class OnionrTests(unittest.TestCase):
|
|||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
else:
|
else:
|
||||||
self.assertTrue(False)
|
self.assertTrue(False)
|
||||||
|
|
||||||
def testQueue(self):
|
def testQueue(self):
|
||||||
logger.debug('--------------------------')
|
logger.debug('--------------------------')
|
||||||
logger.info('Running daemon queue test...')
|
logger.info('Running daemon queue test...')
|
||||||
@ -124,4 +132,5 @@ class OnionrTests(unittest.TestCase):
|
|||||||
if command[0] == 'testCommand':
|
if command[0] == 'testCommand':
|
||||||
if myCore.daemonQueue() == False:
|
if myCore.daemonQueue() == False:
|
||||||
logger.info('Succesfully added and read command')
|
logger.info('Succesfully added and read command')
|
||||||
|
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
@ -16,12 +16,12 @@ import hmac, base64, time, math
|
|||||||
class TimedHMAC:
|
class TimedHMAC:
|
||||||
def __init__(self, base64Key, data, hashAlgo):
|
def __init__(self, base64Key, data, hashAlgo):
|
||||||
'''
|
'''
|
||||||
base64Key = base64 encoded key
|
base64Key = base64 encoded key
|
||||||
data = data to hash
|
data = data to hash
|
||||||
expire = time expiry in epoch
|
expire = time expiry in epoch
|
||||||
hashAlgo = string in hashlib.algorithms_available
|
hashAlgo = string in hashlib.algorithms_available
|
||||||
|
|
||||||
Maximum of 10 seconds grace period
|
Maximum of 10 seconds grace period
|
||||||
'''
|
'''
|
||||||
self.data = data
|
self.data = data
|
||||||
self.expire = math.floor(time.time())
|
self.expire = math.floor(time.time())
|
||||||
@ -30,6 +30,7 @@ class TimedHMAC:
|
|||||||
generatedHMAC = hmac.HMAC(base64.b64decode(base64Key).decode(), digestmod=self.hashAlgo)
|
generatedHMAC = hmac.HMAC(base64.b64decode(base64Key).decode(), digestmod=self.hashAlgo)
|
||||||
generatedHMAC.update(data + expire)
|
generatedHMAC.update(data + expire)
|
||||||
self.HMACResult = generatedHMAC.hexdigest()
|
self.HMACResult = generatedHMAC.hexdigest()
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def check(self, data):
|
def check(self, data):
|
||||||
|
Loading…
Reference in New Issue
Block a user