edited spec, added hmac generation function + test
parent
45eb94d759
commit
19bab6a3c6
|
@ -14,7 +14,7 @@ There are no central servers and all traffic is peer to peer by default (routed
|
||||||
User IDs are simply Tor onion service/I2P host id + PGP fingerprint.
|
User IDs are simply Tor onion service/I2P host id + PGP fingerprint.
|
||||||
Clients consolidate feeds from peers into 1 “timeline” using RSS format.
|
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.
|
Private messages are only accessible by the intended peer based on the PGP id.
|
||||||
Onionr is not intended to be a replacement for Ricochet or OnionShare.
|
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.
|
All traffic is over onion/I2P because if only some was, then that would make that traffic inherently suspicious.
|
||||||
## Goals:
|
## Goals:
|
||||||
• Selective sharing of information with friends & public
|
• Selective sharing of information with friends & public
|
||||||
|
@ -54,6 +54,9 @@ Clients MUST use HTTP(s) to communicate with one another to maintain compatibili
|
||||||
Posts can contain text and images. All posts MUST be time stamped.
|
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.
|
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.
|
All received posts must be verified to be stored and/or displayed to the user.
|
||||||
|
|
||||||
|
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,
|
||||||
|
|
||||||
Posts have two settings:
|
Posts have two settings:
|
||||||
• Friends only:
|
• 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.
|
◦ 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.
|
||||||
|
@ -64,9 +67,9 @@ Clients MUST use HTTP(s) to communicate with one another to maintain compatibili
|
||||||
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.
|
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.
|
When both peers are online messages SHOULD be dispatched directly between peers.
|
||||||
All messages must be verified prior to being displayed.
|
All messages must be verified prior to being displayed.
|
||||||
|
|
||||||
CLients SHOULD allow configurable message padding.
|
Clients SHOULD allow configurable message padding.
|
||||||
## Spam mitigation
|
## 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).
|
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.
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
'''
|
'''
|
||||||
Onionr - P2P Microblogging Platform & Social network.
|
Onionr - P2P Microblogging Platform & Social network.
|
||||||
|
|
||||||
This file contains both the OnionrCommunicate class for communcating with peers
|
This file contains both the OnionrCommunicate class for communcating with peers
|
||||||
and code to operate as a daemon, getting commands from the command queue database (see core.Core.daemonQueue)
|
and code to operate as a daemon, getting commands from the command queue database (see core.Core.daemonQueue)
|
||||||
'''
|
'''
|
||||||
|
@ -39,7 +39,7 @@ class OnionrCommunicate:
|
||||||
return
|
return
|
||||||
def getRemotePeerKey(self, peerID):
|
def getRemotePeerKey(self, peerID):
|
||||||
'''This function contacts a peer and gets their main PGP key.
|
'''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
|
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'
|
||||||
|
@ -70,4 +70,4 @@ if shouldRun:
|
||||||
try:
|
try:
|
||||||
OnionrCommunicate(debug, developmentMode)
|
OnionrCommunicate(debug, developmentMode)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -34,7 +34,7 @@ class Core:
|
||||||
return
|
return
|
||||||
|
|
||||||
def generateMainPGP(self):
|
def generateMainPGP(self):
|
||||||
''' Generate the main PGP key for our client. Should not be done often.
|
''' Generate the main PGP key for our client. Should not be done often.
|
||||||
Uses own PGP home folder in the data/ directory. '''
|
Uses own PGP home folder in the data/ directory. '''
|
||||||
# Generate main pgp key
|
# Generate main pgp key
|
||||||
gpg = gnupg.GPG(homedir='data/pgp/')
|
gpg = gnupg.GPG(homedir='data/pgp/')
|
||||||
|
@ -49,7 +49,7 @@ class Core:
|
||||||
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 users (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
|
||||||
|
@ -62,7 +62,7 @@ class Core:
|
||||||
conn = sqlite3.connect(self.peerDB)
|
conn = sqlite3.connect(self.peerDB)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
c.execute('''
|
c.execute('''
|
||||||
create table users(
|
create table peers(
|
||||||
ID text not null,
|
ID text not null,
|
||||||
name text,
|
name text,
|
||||||
pgpKey text,
|
pgpKey text,
|
||||||
|
@ -74,7 +74,7 @@ class Core:
|
||||||
''')
|
''')
|
||||||
conn.commit()
|
conn.commit()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
def dataDirEncrypt(self, password):
|
def dataDirEncrypt(self, password):
|
||||||
'''
|
'''
|
||||||
Encrypt the data directory on Onionr shutdown
|
Encrypt the data directory on Onionr shutdown
|
||||||
|
@ -149,9 +149,10 @@ class Core:
|
||||||
conn.commit()
|
conn.commit()
|
||||||
conn.close()
|
conn.close()
|
||||||
return
|
return
|
||||||
|
|
||||||
def generateHMAC(self):
|
def generateHMAC(self):
|
||||||
'''
|
'''
|
||||||
generate and return an HMAC key
|
generate and return an HMAC key
|
||||||
'''
|
'''
|
||||||
return
|
key = base64.b64encode(os.urandom(32))
|
||||||
|
return key
|
||||||
|
|
|
@ -90,6 +90,17 @@ class OnionrTests(unittest.TestCase):
|
||||||
myCore.generateMainPGP()
|
myCore.generateMainPGP()
|
||||||
if os.path.exists('data/pgp/'):
|
if os.path.exists('data/pgp/'):
|
||||||
self.assertTrue(True)
|
self.assertTrue(True)
|
||||||
|
def testHMACGen(self):
|
||||||
|
print('--------------------------')
|
||||||
|
print('running daemon queue 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):
|
def testQueue(self):
|
||||||
print('--------------------------')
|
print('--------------------------')
|
||||||
print('running daemon queue test')
|
print('running daemon queue test')
|
||||||
|
@ -110,4 +121,4 @@ class OnionrTests(unittest.TestCase):
|
||||||
if command[0] == 'testCommand':
|
if command[0] == 'testCommand':
|
||||||
if myCore.daemonQueue() == False:
|
if myCore.daemonQueue() == False:
|
||||||
print('Succesfully added and read command')
|
print('Succesfully added and read command')
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
Loading…
Reference in New Issue