diff --git a/.gitignore b/.gitignore
index 0d9c0eda..2a7d956a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,4 @@ onionr/*.pyc
onionr/*.log
onionr/data/hs/hostname
onionr/data/*
+onionr/gnupg/*
diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md
new file mode 100644
index 00000000..874b405d
--- /dev/null
+++ b/ISSUE_TEMPLATE.md
@@ -0,0 +1,12 @@
+# Expected Behavior
+
+# Actual Behavior
+
+# Steps to Reproduce
+
+# Version Information
+Onionr:
+OS:
+Python:
+Tor:
+I2P:
diff --git a/docs/onionr-draft.md b/docs/onionr-draft.md
index 6f0387b9..5ab91cb0 100644
--- a/docs/onionr-draft.md
+++ b/docs/onionr-draft.md
@@ -1,75 +1,51 @@
-# Onionr Protocol Spec
+# Onionr Protocol Spec v2
-A social network/microblogging platform for Tor & I2P
-
-Draft Dec 25 2017
-
-notes:
-Use Blowfish in addition with AES?
+A P2P platform for Tor & I2P
# Overview
Onionr is an encrypted microblogging & mailing system designed in the spirit of Twitter.
There are no central servers and all traffic is peer to peer by default (routed via Tor or I2P).
-User IDs are simply Tor onion service/I2P host id + PGP fingerprint.
-Clients consolidate feeds from peers into 1 “timeline” using RSS format.
-Private messages are only accessible by the intended peer based on the PGP id.
-Onionr is not intended to be a replacement for Ricochet, OnionShare, or Briar.
-All traffic is over onion/I2P because if only some was, then that would make that traffic inherently suspicious.
+User IDs are simply Tor onion service/I2P host id + Ed25519 key fingerprint.
+Private blocks are only able to be read by the intended peer.
+All traffic is over Tor/I2P, connecting only to Tor onion and I2P hidden services.
+
## Goals:
- • Selective sharing of information with friends & public
+ • Selective sharing of information
• Secure & semi-anonymous direct messaging
• Forward secrecy
• Defense in depth
- • Data should be secure for years to come, quantum safe (though not necessarily every “layer”)
+ • Data should be secure for years to come
• Decentralization
* Avoid browser-based exploits that plague similar software
* Avoid timing attacks & unexpected metadata leaks
-## Assumptions:
- • Tor & I2P’s transport protocols & AES-256 are not broken, sha3-512 2nd preimage attacks will remain infeasible indefinitely
- • All traffic is logged indefinitely by powerful adversaries
+
## Protocol
-Clients MUST use HTTP(s) to communicate with one another to maintain compatibility cross platform. HTTPS is recommended, but HTTP is acceptable because Tor & I2P provide transport layer security.
+
+Onionr nodes use HTTP (over Tor/I2P) to exchange keys, metadata, and blocks. Blocks are identified by their sha3_256 hash. Nodes sync a table of blocks hashes and attempt to download blocks they do not yet have from random peers.
+
+Blocks may be encrypted using Curve25519.
+
## Connections
- When a node first comes online, it attempts to bootstrap using a default list provided by a client.
- When two peers connect, they exchange PGP public keys and then generate a shared AES-SHA3-512 HMAC token. These keys are stored in a peer database until expiry.
- HMAC tokens are regenerated either every X many communications with a peer or every X minutes. Every 10 communications or every 24 hours is a recommended default.
- All valid requests with HMAC should be recorded until used HMAC's expiry to prevent replay attacks.
- Peer Types
- * Friends:
- * Encrypted ‘friends only’ posts to one another
- * Usually less strict rate & storage limits
- * OPTIONALLY sign one another’s keys. Users may not want to do this in order to avoid exposing their entire friends list.
- • Strangers:
- * Used for storage of encrypted or public information
- * Can only read public posts
- * Usually stricter rate & storage limits
-## Data Storage/Delivery
- Posts (public or friends only) are stored across the network.
- Private messages SHOULD be delivered directly if both peers are online, otherwise stored in the network.
- Data SHOULD be stored in an entirely encrypted state when a client is offline, including metadata. Data SHOULD be stored in a minimal size with garbage data to ensure some level of plausible deniablity.
- Data SHOULD be stored as long as the node’s user prefers and only erased once disk quota is reached due to new data.
- Posts
- Posts can contain text and images. All posts MUST be time stamped.
- Images SHOULD not be displayed by non-friends by default, to prevent unwanted viewing of offensive material & to reduce attack surface.
- All received posts must be verified to be stored and/or displayed to the user.
+When a node first comes online, it attempts to bootstrap using a default list provided by a client.
+When two peers connect, they exchange Ed25519 keys (if applicable) then Salsa20 keys.
- All data being transfered MUST be encrypted to the end node receiving the data, then the data MUST be encrypted the node(s) transporting/storing the data,
+Salsa20 keys are regenerated either every X many communications with a peer or every X minutes.
- Posts have two settings:
- • Friends only:
- ◦ Posts MUST be encrypted to all trusted peers via AES256-HMAC-SHA256 and PGP signed (signed before encryption) and time stamped to prevent replaying. A temporary RSA key for use in every post (or message) is exchanged every X many configured post (or message), for use in addition with PGP and the HMAC.
- • Public:
- ◦ Posts MUST be PGP signed, and MUST NOT use any encryption.
-## Private Messages
+Every 100kb or every 2 hours is a recommended default.
- Private messages are messages that can have attached images. They MUST be encrypted via AES256-HMAC-SHA256 and PGP signed (signed before encryption) and time stamped to prevent replaying. A temporary RSA key for use in every message is exchanged every X many configured messages (or posts), for use in addition with PGP and the HMAC.
- When both peers are online messages SHOULD be dispatched directly between peers.
- All messages must be verified prior to being displayed.
+All valid requests with HMAC should be recorded until used HMAC's expiry to prevent replay attacks.
+Peer Types
+ * Friends:
+ * Encrypted ‘friends only’ posts to one another
+ * Usually less strict rate & storage limits
+ * Strangers:
+ * Used for storage of encrypted or public information
+ * Can only read public posts
+ * Usually stricter rate & storage limits
- Clients SHOULD allow configurable message padding.
## Spam mitigation
To send or receive data, a node can optionally request that the other node generate a hash that when in hexadecimal representation contains a random string at a random location in the string. Clients will configure what difficulty to request, and what difficulty is acceptable for themselves to perform. Difficulty should correlate with recent network & disk usage and data size. Friends can be configured to have less strict (to non existent) limits, separately from strangers. (proof of work).
-Rate limits can be strict, as Onionr is not intended to be an instant messaging application.
+Rate limits can be strict, as Onionr is not intended to be an instant messaging application.
\ No newline at end of file
diff --git a/onionr/api.py b/onionr/api.py
index a5e75e28..666b7783 100755
--- a/onionr/api.py
+++ b/onionr/api.py
@@ -20,10 +20,10 @@
import flask
from flask import request, Response, abort
from multiprocessing import Process
-import configparser, sys, random, threading, hmac, hashlib, base64, time, math, gnupg, os, logger
+import configparser, sys, random, threading, hmac, hashlib, base64, time, math, os, logger
from core import Core
-import onionrutils
+import onionrutils, onionrcrypto
class API:
'''
Main HTTP API (Flask)
@@ -47,7 +47,7 @@ class API:
if os.path.exists('dev-enabled'):
self._developmentMode = True
logger.set_level(logger.LEVEL_DEBUG)
- logger.warn('DEVELOPMENT MODE ENABLED (THIS IS LESS SECURE!)')
+ #logger.warn('DEVELOPMENT MODE ENABLED (THIS IS LESS SECURE!)')
else:
self._developmentMode = False
logger.set_level(logger.LEVEL_INFO)
@@ -56,6 +56,7 @@ class API:
self.debug = debug
self._privateDelayTime = 3
self._core = Core()
+ self._crypto = onionrcrypto.OnionrCrypto(self._core)
self._utils = onionrutils.OnionrUtils(self._core)
app = flask.Flask(__name__)
bindPort = int(self.config['CLIENT']['PORT'])
@@ -131,14 +132,14 @@ class API:
pass
elif action == 'ping':
resp = Response("pong!")
- elif action == 'setHMAC':
- pass
+ elif action == 'getHMAC':
+ resp = Response(self._crypto.generateSymmetric())
+ elif action == 'getSymmetric':
+ resp = Response(self._crypto.generateSymmetric())
elif action == 'getDBHash':
resp = Response(self._utils.getBlockDBHash())
elif action == 'getBlockHashes':
resp = Response(self._core.getBlockList())
- elif action == 'getPGP':
- resp = Response(self._utils.exportMyPubkey())
# setData should be something the communicator initiates, not this api
elif action == 'getData':
resp = self._core.getData(data)
@@ -171,9 +172,9 @@ class API:
resp = Response("Invalid request")
return resp
-
- logger.info('Starting client on ' + self.host + ':' + str(bindPort) + '...')
- logger.debug('Client token: ' + logger.colors.underline + self.clientToken)
+ if not os.environ.get("WERKZEUG_RUN_MAIN") == "true":
+ logger.info('Starting client on ' + self.host + ':' + str(bindPort) + '...')
+ logger.debug('Client token: ' + logger.colors.underline + self.clientToken)
app.run(host=self.host, port=bindPort, debug=True, threaded=True)
diff --git a/onionr/communicator.py b/onionr/communicator.py
index e7895f47..e6cde1f9 100755
--- a/onionr/communicator.py
+++ b/onionr/communicator.py
@@ -20,7 +20,7 @@ and code to operate as a daemon, getting commands from the command queue databas
along with this program. If not, see .
'''
import sqlite3, requests, hmac, hashlib, time, sys, os, math, logger, urllib.parse
-import core, onionrutils
+import core, onionrutils, onionrcrypto
class OnionrCommunicate:
def __init__(self, debug, developmentMode):
@@ -31,6 +31,7 @@ class OnionrCommunicate:
'''
self._core = core.Core()
self._utils = onionrutils.OnionrUtils(self._core)
+ self._crypto = onionrcrypto.OnionrCrypto(self._core)
blockProcessTimer = 0
blockProcessAmount = 5
heartBeatTimer = 0
@@ -40,13 +41,6 @@ class OnionrCommunicate:
self.peerData = {} # Session data for peers (recent reachability, speed, etc)
- # get our own PGP fingerprint
- fingerprintFile = 'data/own-fingerprint.txt'
- if not os.path.exists(fingerprintFile):
- self._core.generateMainPGP(torID)
- with open(fingerprintFile,'r') as f:
- self.pgpOwnFingerprint = f.read()
- logger.info('My PGP fingerprint is ' + logger.colors.underline + self.pgpOwnFingerprint + logger.colors.reset + logger.colors.fg.green + '.')
if os.path.exists(self._core.queueDB):
self._core.clearDaemonQueue()
while True:
@@ -69,40 +63,7 @@ class OnionrCommunicate:
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
- '''
- url = 'http://' + peerID + '/public/?action=getPGP'
- r = requests.get(url, headers=headers)
- response = r.text
-
- return response
-
- def shareHMAC(self, peerID, key):
- '''
- This function shares an HMAC key to a peer
- '''
-
- return
-
- def getPeerProof(self, peerID):
- '''
- This function gets the current peer proof requirement
- '''
-
- return
-
- def sendPeerProof(self, peerID, data):
- '''
- This function sends the proof result to a peer previously fetched with getPeerProof
- '''
-
- return
-
+
def lookupBlocks(self):
'''
Lookup blocks and merge new ones
diff --git a/onionr/core.py b/onionr/core.py
index d79712db..e8090530 100644
--- a/onionr/core.py
+++ b/onionr/core.py
@@ -17,12 +17,12 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see .
'''
-import sqlite3, os, sys, time, math, gnupg, base64, tarfile, getpass, simplecrypt, hashlib, nacl, logger
-from Crypto.Cipher import AES
-from Crypto import Random
+import sqlite3, os, sys, time, math, base64, tarfile, getpass, simplecrypt, hashlib, nacl, logger
+#from Crypto.Cipher import AES
+#from Crypto import Random
import netcontroller
-import onionrutils
+import onionrutils, onionrcrypto
if sys.version_info < (3, 6):
try:
@@ -38,40 +38,20 @@ class Core:
'''
self.queueDB = 'data/queue.db'
self.peerDB = 'data/peers.db'
- self.ownPGPID = ''
self.blockDB = 'data/blocks.db'
self.blockDataLocation = 'data/blocks/'
- self._utils = onionrutils.OnionrUtils(self)
+ self.addressDB = 'data/address.db'
if not os.path.exists('data/'):
os.mkdir('data/')
if not os.path.exists('data/blocks/'):
os.mkdir('data/blocks/')
-
if not os.path.exists(self.blockDB):
self.createBlockDB()
-
- return
-
- 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
- '''
- 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)
- key = gpg.gen_key(input_data)
- logger.info("Generating PGP key, this will take some time..")
- while key.status != "key created":
- time.sleep(0.5)
- print(key.status)
-
- logger.info("Finished generating PGP key")
- # Write the key
- myFingerpintFile = open('data/own-fingerprint.txt', 'w')
- myFingerpintFile.write(key.fingerprint)
- myFingerpintFile.close()
+
+ self._utils = onionrutils.OnionrUtils(self)
+ # Initialize the crypto object
+ self._crypto = onionrcrypto.OnionrCrypto(self)
return
@@ -82,7 +62,7 @@ class Core:
DOES NO SAFETY CHECKS if the ID is valid, but prepares the insertion
'''
# This function simply adds a peer to the DB
- if not self._utils.validateID(peerID):
+ if not self._utils.validatePubKey(peerID):
return False
conn = sqlite3.connect(self.peerDB)
c = conn.cursor()
@@ -91,6 +71,29 @@ class Core:
conn.commit()
conn.close()
return True
+
+ def createAddressDB(self):
+ '''
+ Generate the address database
+
+ types:
+ 1: I2P b32 address
+ 2: Tor v2 (like facebookcorewwwi.onion)
+ 3: Tor v3
+ '''
+ conn = sqlite3.connect(self.addressDB)
+ c = conn.cursor()
+ c.execute('''CREATE TABLE adders(
+ address text,
+ type int,
+ knownPeer text,
+ speed int,
+ success int,
+ failure int
+ );
+ ''')
+ conn.commit()
+ conn.close()
def createPeerDB(self):
'''
@@ -102,8 +105,7 @@ class Core:
c.execute('''CREATE TABLE peers(
ID text not null,
name text,
- pgpKey text,
- hmacKey text,
+ adders text,
blockDBHash text,
forwardKey text,
dateSeen not null,
@@ -112,7 +114,6 @@ class Core:
''')
conn.commit()
conn.close()
-
return
def createBlockDB(self):
@@ -300,14 +301,6 @@ class Core:
return
- def generateHMAC(self, length=32):
- '''
- Generate and return an HMAC key
- '''
- key = base64.b64encode(os.urandom(length))
-
- return key
-
def listPeers(self, randomOrder=True):
'''
Return a list of peers
@@ -322,7 +315,7 @@ class Core:
peers = c.execute('SELECT * FROM peers;')
peerList = []
for i in peers:
- peerList.append(i[0])
+ peerList.append(i[2])
conn.close()
return peerList
@@ -333,18 +326,17 @@ class Core:
id text 0
name text, 1
- pgpKey text, 2
- hmacKey text, 3
- blockDBHash text, 4
- forwardKey text, 5
- dateSeen not null, 7
- bytesStored int, 8
- trust int 9
+ adders text, 2
+ blockDBHash text, 3
+ forwardKey text, 4
+ dateSeen not null, 5
+ bytesStored int, 6
+ trust int 7
'''
conn = sqlite3.connect(self.peerDB)
c = conn.cursor()
command = (peer,)
- infoNumbers = {'id': 0, 'name': 1, 'pgpKey': 2, 'hmacKey': 3, 'blockDBHash': 4, 'forwardKey': 5, 'dateSeen': 6, 'bytesStored': 7, 'trust': 8}
+ infoNumbers = {'id': 0, 'name': 1, 'adders': 2, 'blockDBHash': 3, 'forwardKey': 4, 'dateSeen': 5, 'bytesStored': 6, 'trust': 7}
info = infoNumbers[info]
iterCount = 0
retVal = ''
@@ -367,7 +359,7 @@ class Core:
c = conn.cursor()
command = (data, peer)
# TODO: validate key on whitelist
- if key not in ('id', 'text', 'name', 'pgpKey', 'hmacKey', 'blockDBHash', 'forwardKey', 'dateSeen', 'bytesStored', 'trust'):
+ if key not in ('id', 'name', 'pubkey', 'blockDBHash', 'forwardKey', 'dateSeen', 'bytesStored', 'trust'):
raise Exception("Got invalid database key when setting peer info")
c.execute('UPDATE peers SET ' + key + ' = ? WHERE id=?', command)
conn.commit()
diff --git a/onionr/netcontroller.py b/onionr/netcontroller.py
index dcb3c3a5..058d8e4a 100644
--- a/onionr/netcontroller.py
+++ b/onionr/netcontroller.py
@@ -103,7 +103,12 @@ HiddenServicePort 80 127.0.0.1:''' + str(self.hsPort) + '''
int(pidN)
except:
return
- os.kill(int(pidN), signal.SIGTERM)
- os.remove('data/torPid.txt')
+ try:
+ os.kill(int(pidN), signal.SIGTERM)
+ os.remove('data/torPid.txt')
+ except ProcessLookupError:
+ pass
+ except FileNotFoundError:
+ pass
return
diff --git a/onionr/onionr.py b/onionr/onionr.py
index 9c12b1b7..d3c51a4f 100755
--- a/onionr/onionr.py
+++ b/onionr/onionr.py
@@ -47,7 +47,6 @@ class Onionr:
if os.path.exists('dev-enabled'):
self._developmentMode = True
logger.set_level(logger.LEVEL_DEBUG)
- logger.warn('DEVELOPMENT MODE ENABLED (THIS IS LESS SECURE!)')
else:
self._developmentMode = False
logger.set_level(logger.LEVEL_INFO)
@@ -128,6 +127,7 @@ class Onionr:
'addmessage': self.addMessage,
'add-msg': self.addMessage,
'add-message': self.addMessage,
+ 'pm': self.sendEncrypt,
'gui': self.openGUI,
'addpeer': self.addPeer,
'add-peer': self.addPeer
@@ -150,6 +150,19 @@ class Onionr:
logger.info('Onionr ' + ONIONR_VERSION + ' (' + platform.machine() + ') : API v' + API_VERSION)
logger.info('Running on ' + platform.platform() + ' ' + platform.release())
+ def sendEncrypt(self):
+ '''Create a private message and send it'''
+ while True:
+ peer = logger.readline('Peer to send to: ')
+ if self.onionrUtils.validateID(peer):
+ break
+ else:
+ logger.error('Invalid peer ID')
+ message = logger.readline("Enter a message: ")
+ logger.info("Sending message to " + peer)
+ self.onionrUtils.sendPM(peer, message)
+
+
def openGUI(self):
gui.OnionrGUI(self.onionrCore)
@@ -197,11 +210,14 @@ class Onionr:
def daemon(self):
''' Start the Onionr communication daemon '''
if not os.environ.get("WERKZEUG_RUN_MAIN") == "true":
+ if self._developmentMode:
+ logger.warn('DEVELOPMENT MODE ENABLED (THIS IS LESS SECURE!)')
net = NetController(self.config['CLIENT']['PORT'])
logger.info('Tor is starting...')
if not net.startTor():
sys.exit(1)
logger.info('Started Tor .onion service: ' + logger.colors.underline + net.myID)
+ logger.info('Our Public key: ' + self.onionrCore._crypto.pubKey)
time.sleep(1)
subprocess.Popen(["./communicator.py", "run", str(net.socksPort)])
logger.debug('Started communicator')
diff --git a/onionr/onionrcrypto.py b/onionr/onionrcrypto.py
index fed23889..6b282341 100644
--- a/onionr/onionrcrypto.py
+++ b/onionr/onionrcrypto.py
@@ -17,17 +17,51 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see .
'''
-import nacl
+import nacl.signing, nacl.encoding, nacl.public, os
class OnionrCrypto:
- def __init__(self):
+ def __init__(self, coreInstance):
+ self._core = coreInstance
+ self._keyFile = 'data/keys.txt'
+ self.pubKey = None
+ self.privKey = None
+
+ # Load our own pub/priv Ed25519 keys, gen & save them if they don't exist
+ if os.path.exists(self._keyFile):
+ with open('data/keys.txt', 'r') as keys:
+ keys = keys.read().split(',')
+ self.pubKey = keys[0]
+ self.privKey = keys[1]
+ else:
+ keys = self.generatePubKey()
+ self.pubKey = keys[0]
+ self.privKey = keys[1]
+ with open(self._keyFile, 'w') as keyfile:
+ keyfile.write(self.pubKey + ',' + self.privKey)
return
- def symmetricPeerEncrypt(self, data, key):
+ def pubKeyEncrypt(self, data, peer):
+ '''Encrypt to a peers public key (Curve25519, taken from Ed25519 pubkey)'''
return
- def symmetricPeerDecrypt(self, data, key):
+ def pubKeyEncrypt(self, data, peer):
+ '''pubkey decrypt (Curve25519, taken from Ed25519 pubkey)'''
return
- def rsaEncrypt(self, peer, data):
+ def symmetricPeerEncrypt(self, data):
+ '''Salsa20 encrypt data to peer (with mac)'''
return
+
+ def symmetricPeerDecrypt(self, data, peer):
+ '''Salsa20 decrypt data from peer (with mac)'''
+ return
+
+ def generateSymmetric(self, data, peer):
+ '''Generate symmetric key'''
+ return
+
+ def generatePubKey(self):
+ '''Generate a Ed25519 public key pair, return tuple of base64encoded 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())
\ No newline at end of file
diff --git a/onionr/onionrutils.py b/onionr/onionrutils.py
index ca575073..b000e799 100644
--- a/onionr/onionrutils.py
+++ b/onionr/onionrutils.py
@@ -18,7 +18,8 @@
along with this program. If not, see .
'''
# Misc functions that do not fit in the main api, but are useful
-import getpass, sys, requests, configparser, os, socket, gnupg, hashlib, logger, sqlite3
+import getpass, sys, requests, configparser, os, socket, hashlib, logger, sqlite3
+import nacl.signing, nacl.encoding
if sys.version_info < (3, 6):
try:
import sha3
@@ -93,19 +94,6 @@ class OnionrUtils:
else:
return True
- def exportMyPubkey(self):
- '''
- Export our PGP key if it exists
- '''
- if not os.path.exists(self.fingerprintFile):
- raise Exception("No fingerprint found, cannot export our PGP key.")
- gpg = gnupg.GPG(homedir='./data/pgp/')
- with open(self.fingerprintFile,'r') as f:
- fingerprint = f.read()
- ascii_armored_public_keys = gpg.export_keys(fingerprint)
-
- return ascii_armored_public_keys
-
def getBlockDBHash(self):
'''
Return a sha3_256 hash of the blocks DB
@@ -153,10 +141,22 @@ class OnionrUtils:
retVal = False
return retVal
+
+ def validatePubKey(self, key):
+ '''Validate if a string is a valid base32 encoded Ed25519 key'''
+ retVal = False
+ try:
+ nacl.signing.SigningKey(seed=key, encoder=nacl.encoding.Base32Encoder)
+ except nacl.exceptions.ValueError:
+ pass
+ else:
+ retVal = True
+ return retVal
+
def validateID(self, id):
'''
- Validate if a user ID is a valid tor or i2p hidden service
+ Validate if an address is a valid tor or i2p hidden service
'''
idLength = len(id)
retVal = True
@@ -196,4 +196,4 @@ class OnionrUtils:
if not idNoDomain.isalnum():
retVal = False
- return retVal
+ return retVal
\ No newline at end of file
diff --git a/onionr/tests.py b/onionr/tests.py
index 8babbdfd..5728055c 100755
--- a/onionr/tests.py
+++ b/onionr/tests.py
@@ -54,7 +54,7 @@ class OnionrTests(unittest.TestCase):
myCore = core.Core()
if not os.path.exists('data/peers.db'):
myCore.createPeerDB()
- if myCore.addPeer('2ks5c5bm6zk3ejqg.onion') and not myCore.addPeer('invalidpeer.onion'):
+ if myCore.addPeer('6M5MXL237OK57ITHVYN5WGHANPGOMKS5C3PJLHBBNKFFJQOIDOJA====') and not myCore.addPeer('NFXHMYLMNFSAU==='):
self.assertTrue(True)
else:
self.assertTrue(False)
@@ -85,33 +85,6 @@ class OnionrTests(unittest.TestCase):
else:
self.assertTrue(False)
- def testPGPGen(self):
- logger.debug('--------------------------')
- logger.info('Running PGP key generation test...')
- if os.path.exists('data/pgp/'):
- self.assertTrue(True)
- else:
- import core, netcontroller
- myCore = core.Core()
- net = netcontroller.NetController(1337)
- net.startTor()
- torID = open('data/hs/hostname').read()
- myCore.generateMainPGP(torID)
- if os.path.exists('data/pgp/'):
- self.assertTrue(True)
-
- def testHMACGen(self):
- logger.debug('--------------------------')
- logger.info('Running HMAC generation test...')
- # Test if hmac key generation is working
- import core
- myCore = core.Core()
- key = myCore.generateHMAC()
- if len(key) > 10:
- self.assertTrue(True)
- else:
- self.assertTrue(False)
-
def testQueue(self):
logger.debug('--------------------------')
logger.info('Running daemon queue test...')
diff --git a/readme.md b/readme.md
index 730d1270..c90492e9 100644
--- a/readme.md
+++ b/readme.md
@@ -2,17 +2,27 @@
[![Build Status](https://travis-ci.org/beardog108/onionr.svg?branch=master)](https://travis-ci.org/beardog108/onionr)
-P2P microblogging platform and social network, using Tor & I2P.
+P2P platform, using Tor & I2P.
Major work in progress.
***THIS SOFTWARE IS NOT USABLE OR SAFE YET.***
+**Roadmap/features:**
+
+* [X] Fully p2p/decentralized, no trackers or other single points of failure
+* [X] High level of anonymity
+* [ ] End to end encryption where applicable
+* [X] Optional non-encrypted blocks, useful for blog posts or public file sharing
+* [ ] Easy API system for integration to websites
+
# Development
This software is in heavy development. If for some reason you want to get involved, get in touch first.
+**Onionr API and functionality is subject to non-backwards compatible change during development**
+
## Disclaimer
The Tor Project, I2P developers, and anyone else do not own, create, or endorse this project, and are not otherwise involved.
diff --git a/requirements.txt b/requirements.txt
index da4c8869..77e25537 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,10 +1,7 @@
PyNaCl==1.2.1
-gnupg==2.3.1
+requests==2.12.4
Flask==0.12.2
-requests==2.18.4
-urllib3==1.22
simple_crypt==4.1.7
+urllib3==1.19.1
sha3==0.2.1
-pycrypto==2.6.1
-pynacl==1.2.1
PySocks==1.6.8
diff --git a/reset.sh b/reset.sh
new file mode 100755
index 00000000..eaf6641b
--- /dev/null
+++ b/reset.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+echo "RESETING ONIONR"
+rm onionr/data/blocks/*.dat
+rm onionr/data/peers.db
+rm onionr/data/blocks.db