Merge branch 'crypto' of https://github.com/beardog108/Onionr into crypto
commit
36d9ebd4f1
|
@ -68,6 +68,8 @@ class API:
|
|||
self.clientToken = config.get('client')['client_hmac']
|
||||
self.timeBypassToken = base64.b16encode(os.urandom(32)).decode()
|
||||
|
||||
self.mimeType = 'text/plain'
|
||||
|
||||
with open('data/time-bypass.txt', 'w') as bypass:
|
||||
bypass.write(self.timeBypassToken)
|
||||
|
||||
|
@ -96,12 +98,17 @@ class API:
|
|||
def afterReq(resp):
|
||||
if not self.requestFailed:
|
||||
resp.headers['Access-Control-Allow-Origin'] = '*'
|
||||
else:
|
||||
resp.headers['server'] = 'Onionr'
|
||||
resp.headers['Content-Type'] = 'text/plain'
|
||||
resp.headers["Content-Security-Policy"] = "default-src 'none'"
|
||||
#else:
|
||||
# resp.headers['server'] = 'Onionr'
|
||||
resp.headers['Content-Type'] = self.mimeType
|
||||
resp.headers["Content-Security-Policy"] = "default-src 'none'; script-src 'none'; object-src 'none'; style-src data: 'unsafe-inline'; img-src data:; media-src 'none'; frame-src 'none'; font-src 'none'; connect-src 'none'"
|
||||
resp.headers['X-Frame-Options'] = 'deny'
|
||||
resp.headers['X-Content-Type-Options'] = "nosniff"
|
||||
resp.headers['server'] = 'Onionr'
|
||||
|
||||
# reset to text/plain to help prevent browser attacks
|
||||
if self.mimeType != 'text/plain':
|
||||
self.mimeType = 'text/plain'
|
||||
|
||||
return resp
|
||||
|
||||
|
@ -111,6 +118,11 @@ class API:
|
|||
timingToken = ''
|
||||
else:
|
||||
timingToken = request.args.get('timingToken')
|
||||
data = request.args.get('data')
|
||||
try:
|
||||
data = data
|
||||
except:
|
||||
data = ''
|
||||
startTime = math.floor(time.time())
|
||||
# we should keep a hash DB of requests (with hmac) to prevent replays
|
||||
action = request.args.get('action')
|
||||
|
@ -129,6 +141,15 @@ class API:
|
|||
resp = Response('pong')
|
||||
elif action == 'stats':
|
||||
resp = Response('me_irl')
|
||||
elif action == 'site':
|
||||
block = data
|
||||
siteData = self._core.getData(data)
|
||||
response = 'not found'
|
||||
if siteData != '' and siteData != False:
|
||||
self.mimeType = 'text/html'
|
||||
response = siteData.split(b'-', 2)[-1]
|
||||
resp = Response(response)
|
||||
|
||||
else:
|
||||
resp = Response('(O_o) Dude what? (invalid command)')
|
||||
endTime = math.floor(time.time())
|
||||
|
@ -149,7 +170,7 @@ class API:
|
|||
requestingPeer = request.args.get('myID')
|
||||
data = request.args.get('data')
|
||||
try:
|
||||
data
|
||||
data = data
|
||||
except:
|
||||
data = ''
|
||||
if action == 'firstConnect':
|
||||
|
@ -175,7 +196,9 @@ class API:
|
|||
resp = Response('')
|
||||
# setData should be something the communicator initiates, not this api
|
||||
elif action == 'getData':
|
||||
resp = self._core.getData(data)
|
||||
if self._utils.validateHash(data):
|
||||
if not os.path.exists('data/blocks/' + data + '.db'):
|
||||
resp = base64.b64encode(self._core.getData(data))
|
||||
if resp == False:
|
||||
abort(404)
|
||||
resp = ""
|
||||
|
|
|
@ -19,7 +19,7 @@ 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
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
'''
|
||||
import sqlite3, requests, hmac, hashlib, time, sys, os, math, logger, urllib.parse, random
|
||||
import sqlite3, requests, hmac, hashlib, time, sys, os, math, logger, urllib.parse, random, base64, binascii
|
||||
import core, onionrutils, onionrcrypto, netcontroller, onionrproofs, btc, config, onionrplugins as plugins
|
||||
|
||||
class OnionrCommunicate:
|
||||
|
@ -241,17 +241,21 @@ class OnionrCommunicate:
|
|||
data = self.performGet('getData', i, hash)
|
||||
if data == False or len(data) > 10000000:
|
||||
continue
|
||||
hasher.update(data.encode())
|
||||
try:
|
||||
data = base64.b64decode(data)
|
||||
except binascii.Error:
|
||||
data = b''
|
||||
hasher.update(data)
|
||||
digest = hasher.hexdigest()
|
||||
if type(digest) is bytes:
|
||||
digest = digest.decode()
|
||||
if digest == hash.strip():
|
||||
self._core.setData(data)
|
||||
if data.startswith('-txt-'):
|
||||
self._core.setBlockType(hash, 'txt')
|
||||
logger.info('Successfully obtained data for ' + hash, timestamp=True)
|
||||
if data.startswith(b'-txt-'):
|
||||
self._core.setBlockType(hash, 'txt')
|
||||
if len(data) < 120:
|
||||
logger.debug('Block text:\n' + data)
|
||||
logger.debug('Block text:\n' + data.decode())
|
||||
else:
|
||||
logger.warn("Failed to validate " + hash + " " + " hash calculated was " + digest)
|
||||
|
||||
|
@ -263,7 +267,7 @@ class OnionrCommunicate:
|
|||
'''
|
||||
return urllib.parse.quote_plus(data)
|
||||
|
||||
def performGet(self, action, peer, data=None, skipHighFailureAddress=False, peerType='tor'):
|
||||
def performGet(self, action, peer, data=None, skipHighFailureAddress=False, peerType='tor', selfCheck=True):
|
||||
'''
|
||||
Performs a request to a peer through Tor or i2p (currently only Tor)
|
||||
'''
|
||||
|
@ -271,6 +275,13 @@ class OnionrCommunicate:
|
|||
if not peer.endswith('.onion') and not peer.endswith('.onion/'):
|
||||
raise PeerError('Currently only Tor .onion peers are supported. You must manually specify .onion')
|
||||
|
||||
if len(self._core.hsAdder.strip()) == 0:
|
||||
raise Exception("Could not perform self address check in performGet due to not knowing our address")
|
||||
if selfCheck:
|
||||
if peer.replace('/', '') == self._core.hsAdder:
|
||||
logger.warn('Tried to performget to own hidden service, but selfCheck was not set to false')
|
||||
return
|
||||
|
||||
# Store peer in peerData dictionary (non permanent)
|
||||
if not peer in self.peerData:
|
||||
self.peerData[peer] = {'connectCount': 0, 'failCount': 0, 'lastConnectTime': math.floor(time.time())}
|
||||
|
|
|
@ -44,6 +44,9 @@ class Core:
|
|||
self.addressDB = 'data/address.db'
|
||||
self.hsAdder = ''
|
||||
|
||||
self.bootstrapFileLocation = 'static-data/bootstrap-nodes.txt'
|
||||
self.bootstrapList = []
|
||||
|
||||
if not os.path.exists('data/'):
|
||||
os.mkdir('data/')
|
||||
if not os.path.exists('data/blocks/'):
|
||||
|
@ -55,9 +58,19 @@ class Core:
|
|||
with open('data/hs/hostname', 'r') as hs:
|
||||
self.hsAdder = hs.read()
|
||||
|
||||
# Load bootstrap address list
|
||||
if os.path.exists(self.bootstrapFileLocation):
|
||||
with open(self.bootstrapFileLocation, 'r') as bootstrap:
|
||||
bootstrap = bootstrap.read()
|
||||
for i in bootstrap.split('\n'):
|
||||
self.bootstrapList.append(i)
|
||||
else:
|
||||
logger.warn('Warning: address bootstrap file not found ' + self.bootstrapFileLocation)
|
||||
|
||||
self._utils = onionrutils.OnionrUtils(self)
|
||||
# Initialize the crypto object
|
||||
self._crypto = onionrcrypto.OnionrCrypto(self)
|
||||
|
||||
except Exception as error:
|
||||
logger.error('Failed to initialize core Onionr library.', error=error)
|
||||
logger.fatal('Cannot recover from error.')
|
||||
|
@ -245,7 +258,7 @@ class Core:
|
|||
Simply return the data associated to a hash
|
||||
'''
|
||||
try:
|
||||
dataFile = open(self.blockDataLocation + hash + '.dat')
|
||||
dataFile = open(self.blockDataLocation + hash + '.dat', 'rb')
|
||||
data = dataFile.read()
|
||||
dataFile.close()
|
||||
except FileNotFoundError:
|
||||
|
@ -257,8 +270,10 @@ class Core:
|
|||
'''
|
||||
Set the data assciated with a hash
|
||||
'''
|
||||
data = data.encode()
|
||||
data = data
|
||||
hasher = hashlib.sha3_256()
|
||||
if not type(data) is bytes:
|
||||
data = data.encode()
|
||||
hasher.update(data)
|
||||
dataHash = hasher.hexdigest()
|
||||
if type(dataHash) is bytes:
|
||||
|
@ -268,8 +283,8 @@ class Core:
|
|||
pass # TODO: properly check if block is already saved elsewhere
|
||||
#raise Exception("Data is already set for " + dataHash)
|
||||
else:
|
||||
blockFile = open(blockFileName, 'w')
|
||||
blockFile.write(data.decode())
|
||||
blockFile = open(blockFileName, 'wb')
|
||||
blockFile.write(data)
|
||||
blockFile.close()
|
||||
|
||||
conn = sqlite3.connect(self.blockDB)
|
||||
|
@ -574,8 +589,10 @@ class Core:
|
|||
announceAmount = 2
|
||||
nodeList = self.listAdders()
|
||||
if len(nodeList) == 0:
|
||||
self.addAddress('onionragxuddecmg.onion')
|
||||
nodeList.append('onionragxuddecmg.onion')
|
||||
for i in self.bootstrapList:
|
||||
if self._utils.validateID(i):
|
||||
self.addAddress(i)
|
||||
nodeList.append(i)
|
||||
if announceAmount > len(nodeList):
|
||||
announceAmount = len(nodeList)
|
||||
for i in range(announceAmount):
|
||||
|
|
|
@ -34,7 +34,7 @@ except ImportError:
|
|||
|
||||
ONIONR_TAGLINE = 'Anonymous P2P Platform - GPLv3 - https://Onionr.VoidNet.Tech'
|
||||
ONIONR_VERSION = '0.0.0' # for debugging and stuff
|
||||
API_VERSION = '1' # increments of 1; only change when something fundemental about how the API works changes. This way other nodes knows how to communicate without learning too much information about you.
|
||||
API_VERSION = '2' # increments of 1; only change when something fundemental about how the API works changes. This way other nodes knows how to communicate without learning too much information about you.
|
||||
|
||||
class Onionr:
|
||||
def __init__(self):
|
||||
|
@ -179,6 +179,7 @@ class Onionr:
|
|||
'add-addr': self.addAddress,
|
||||
'addaddr': self.addAddress,
|
||||
'addaddress': self.addAddress,
|
||||
'addfile': self.addFile,
|
||||
|
||||
'introduce': self.onionrCore.introduceNode,
|
||||
'connect': self.addAddress
|
||||
|
@ -200,6 +201,7 @@ class Onionr:
|
|||
'add-msg': 'Broadcasts a message to the Onionr network',
|
||||
'pm': 'Adds a private message to block',
|
||||
'get-pms': 'Shows private messages sent to you',
|
||||
'addfile': 'Create an Onionr block from a file',
|
||||
'introduce': 'Introduce your node to the public Onionr network (DAEMON MUST BE RUNNING)',
|
||||
}
|
||||
|
||||
|
@ -373,7 +375,7 @@ class Onionr:
|
|||
addedHash = self.onionrCore.setData(messageToAdd)
|
||||
self.onionrCore.addToBlockDB(addedHash, selfInsert=True)
|
||||
self.onionrCore.setBlockType(addedHash, 'txt')
|
||||
|
||||
logger.info("inserted your message as block: " + addedHash)
|
||||
return
|
||||
|
||||
def getPMs(self):
|
||||
|
@ -557,8 +559,23 @@ class Onionr:
|
|||
retVal = ''
|
||||
try:
|
||||
with open('./data/hs/hostname', 'r') as hostname:
|
||||
retval = retVal.read()
|
||||
retVal = hostname.read()
|
||||
except FileNotFoundError:
|
||||
return retVal
|
||||
|
||||
def addFile(self):
|
||||
'''command to add a file to the onionr network'''
|
||||
if len(sys.argv) >= 2:
|
||||
newFile = sys.argv[2]
|
||||
logger.info('Attempting to add file...')
|
||||
try:
|
||||
with open(newFile, 'r') as new:
|
||||
new = new.read()
|
||||
except FileNotFoundError:
|
||||
logger.warn('That file does not exist. Improper path?')
|
||||
else:
|
||||
print(new)
|
||||
self.onionrCore.insertBlock(new, header='bin')
|
||||
|
||||
|
||||
Onionr()
|
||||
|
|
|
@ -167,7 +167,7 @@ class OnionrCrypto:
|
|||
return binascii.hexlify(nacl.utils.random(nacl.secret.SecretBox.KEY_SIZE))
|
||||
|
||||
def generatePubKey(self):
|
||||
'''Generate a Ed25519 public key pair, return tuple of base64encoded pubkey, privkey'''
|
||||
'''Generate a Ed25519 public key pair, return tuple of base32encoded pubkey, privkey'''
|
||||
private_key = nacl.signing.SigningKey.generate()
|
||||
public_key = private_key.verify_key.encode(encoder=nacl.encoding.Base32Encoder())
|
||||
return (public_key.decode(), private_key.encode(encoder=nacl.encoding.Base32Encoder()).decode())
|
|
@ -0,0 +1,3 @@
|
|||
onionisrgccylxpr.onion
|
||||
aaronk3mcmglj6qedwptg62yl3wxxjwba2ucpoobrn7iudcacdxtrfad.onion
|
||||
onionragxuddecmg.onion
|
Loading…
Reference in New Issue