fixed forward secrecy and delete keys

This commit is contained in:
Kevin Froman 2018-11-09 13:07:26 -06:00
parent c0707a10f9
commit c0c5061f1e
No known key found for this signature in database
GPG Key ID: 0D414D0FE405B63B
6 changed files with 60 additions and 16 deletions

View File

@ -99,11 +99,13 @@ class OnionrCommunicatorDaemon:
netCheckTimer = OnionrCommunicatorTimers(self, self.daemonTools.netCheck, 600) netCheckTimer = OnionrCommunicatorTimers(self, self.daemonTools.netCheck, 600)
announceTimer = OnionrCommunicatorTimers(self, self.daemonTools.announceNode, 305, requiresPeer=True, maxThreads=1) announceTimer = OnionrCommunicatorTimers(self, self.daemonTools.announceNode, 305, requiresPeer=True, maxThreads=1)
cleanupTimer = OnionrCommunicatorTimers(self, self.peerCleanup, 300, requiresPeer=True) cleanupTimer = OnionrCommunicatorTimers(self, self.peerCleanup, 300, requiresPeer=True)
forwardSecrecyTimer = OnionrCommunicatorTimers(self, self.daemonTools.cleanKeys, 15)
# set loop to execute instantly to load up peer pool (replaced old pool init wait) # set loop to execute instantly to load up peer pool (replaced old pool init wait)
peerPoolTimer.count = (peerPoolTimer.frequency - 1) peerPoolTimer.count = (peerPoolTimer.frequency - 1)
cleanupTimer.count = (cleanupTimer.frequency - 60) cleanupTimer.count = (cleanupTimer.frequency - 60)
announceTimer.count = (cleanupTimer.frequency - 60) announceTimer.count = (cleanupTimer.frequency - 60)
#forwardSecrecyTimer.count = (forwardSecrecyTimer.frequency - 990)
self.socketServer = threading.Thread(target=onionrsockets.OnionrSocketServer, args=(self._core,)) self.socketServer = threading.Thread(target=onionrsockets.OnionrSocketServer, args=(self._core,))
self.socketServer.start() self.socketServer.start()
@ -450,7 +452,10 @@ class OnionrCommunicatorDaemon:
if cmd[0] == 'shutdown': if cmd[0] == 'shutdown':
self.shutdown = True self.shutdown = True
elif cmd[0] == 'announceNode': elif cmd[0] == 'announceNode':
self.announce(cmd[1]) if len(self.onlinePeers) > 0:
self.announce(cmd[1])
else:
logger.warn("Not introducing, since I have no connected nodes.")
elif cmd[0] == 'runCheck': elif cmd[0] == 'runCheck':
logger.debug('Status check; looks good.') logger.debug('Status check; looks good.')
open(self._core.dataDir + '.runcheck', 'w+').close() open(self._core.dataDir + '.runcheck', 'w+').close()

View File

@ -670,7 +670,7 @@ class Core:
except AttributeError: except AttributeError:
pass pass
if encryptType == 'sym': if encryptType == 'asym':
try: try:
forwardEncrypted = onionrusers.OnionrUser(self, asymPeer).forwardEncrypt(data) forwardEncrypted = onionrusers.OnionrUser(self, asymPeer).forwardEncrypt(data)
data = forwardEncrypted[0] data = forwardEncrypted[0]

View File

@ -124,8 +124,8 @@ class DBCreator:
c = conn.cursor() c = conn.cursor()
c.execute('''CREATE TABLE myForwardKeys( c.execute('''CREATE TABLE myForwardKeys(
peer text not null, peer text not null,
public key text not null, publickey text not null,
private key text not null, privatekey text not null,
date int not null, date int not null,
expire int not null expire int not null
); );

View File

@ -17,7 +17,7 @@
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 onionrexceptions, onionrpeers, onionrproofs, base64, logger import onionrexceptions, onionrpeers, onionrproofs, base64, logger, onionrusers, sqlite3
from dependencies import secrets from dependencies import secrets
class DaemonTools: class DaemonTools:
def __init__(self, daemon): def __init__(self, daemon):
@ -79,6 +79,26 @@ class DaemonTools:
self.daemon._core.removeBlock(bHash) self.daemon._core.removeBlock(bHash)
self.daemon.decrementThreadCount('cleanOldBlocks') self.daemon.decrementThreadCount('cleanOldBlocks')
def cleanKeys(self):
'''Delete expired forward secrecy keys'''
conn = sqlite3.connect(self.daemon._core.peerDB, timeout=10)
c = conn.cursor()
time = self.daemon._core._utils.getEpoch()
deleteKeys = []
for entry in c.execute("SELECT * FROM forwardKeys where expire <= ?", (time,)):
logger.info(entry[1])
deleteKeys.append(entry[1])
for key in deleteKeys:
logger.info('Deleting forward key '+ key)
c.execute("DELETE from forwardKeys where forwardKey = ?", (key,))
conn.commit()
conn.close()
onionrusers.deleteExpiredKeys(self.daemon._core)
self.daemon.decrementThreadCount('cleanKeys')
def cooldownPeer(self): def cooldownPeer(self):
'''Randomly add an online peer to cooldown, so we can connect a new one''' '''Randomly add an online peer to cooldown, so we can connect a new one'''
onlinePeerAmount = len(self.daemon.onlinePeers) onlinePeerAmount = len(self.daemon.onlinePeers)

View File

@ -19,6 +19,19 @@
''' '''
import onionrblockapi, logger, onionrexceptions, json, sqlite3 import onionrblockapi, logger, onionrexceptions, json, sqlite3
import nacl.exceptions import nacl.exceptions
def deleteExpiredKeys(coreInst):
# Fetch the keys we generated for the peer, that are still around
conn = sqlite3.connect(coreInst.forwardKeysFile, timeout=10)
c = conn.cursor()
curTime = coreInst._utils.getEpoch()
c.execute("DELETE from myForwardKeys where expire <= ?", (curTime,))
conn.commit()
conn.execute("VACUUM")
conn.close()
return
class OnionrUser: class OnionrUser:
def __init__(self, coreInst, publicKey): def __init__(self, coreInst, publicKey):
self.trust = 0 self.trust = 0
@ -58,7 +71,7 @@ class OnionrUser:
def forwardEncrypt(self, data): def forwardEncrypt(self, data):
retData = '' retData = ''
forwardKey = self._getLatestForwardKey() forwardKey = self._getLatestForwardKey()
logger.info('using ' + forwardKey) #logger.info('using ' + forwardKey)
if self._core._utils.validatePubKey(forwardKey): if self._core._utils.validatePubKey(forwardKey):
retData = self._core._crypto.pubKeyEncrypt(data, forwardKey, encodedData=True, anonymous=True) retData = self._core._crypto.pubKeyEncrypt(data, forwardKey, encodedData=True, anonymous=True)
else: else:
@ -68,9 +81,9 @@ class OnionrUser:
def forwardDecrypt(self, encrypted): def forwardDecrypt(self, encrypted):
retData = "" retData = ""
logger.error(self.publicKey) #logger.error(self.publicKey)
logger.error(self.getGeneratedForwardKeys()) #logger.error(self.getGeneratedForwardKeys(False))
for key in self.getGeneratedForwardKeys(): for key in self.getGeneratedForwardKeys(False):
logger.info(encrypted) logger.info(encrypted)
try: try:
retData = self._core._crypto.pubKeyDecrypt(encrypted, privkey=key[1], anonymous=True, encodedData=True) retData = self._core._crypto.pubKeyDecrypt(encrypted, privkey=key[1], anonymous=True, encodedData=True)
@ -109,7 +122,7 @@ class OnionrUser:
return list(keyList) return list(keyList)
def generateForwardKey(self, expire=432000): def generateForwardKey(self, expire=604800):
# Generate a forward secrecy key for the peer # Generate a forward secrecy key for the peer
conn = sqlite3.connect(self._core.forwardKeysFile, timeout=10) conn = sqlite3.connect(self._core.forwardKeysFile, timeout=10)
@ -121,7 +134,7 @@ class OnionrUser:
newPriv = self._core._utils.bytesToStr(newKeys[1]) newPriv = self._core._utils.bytesToStr(newKeys[1])
time = self._core._utils.getEpoch() time = self._core._utils.getEpoch()
command = (self.publicKey, newPub, newPriv, time, expire) command = (self.publicKey, newPub, newPriv, time, expire + time)
c.execute("INSERT INTO myForwardKeys VALUES(?, ?, ?, ?, ?);", command) c.execute("INSERT INTO myForwardKeys VALUES(?, ?, ?, ?, ?);", command)
@ -129,7 +142,7 @@ class OnionrUser:
conn.close() conn.close()
return newPub return newPub
def getGeneratedForwardKeys(self): def getGeneratedForwardKeys(self, genNew=True):
# Fetch the keys we generated for the peer, that are still around # Fetch the keys we generated for the peer, that are still around
conn = sqlite3.connect(self._core.forwardKeysFile, timeout=10) conn = sqlite3.connect(self._core.forwardKeysFile, timeout=10)
c = conn.cursor() c = conn.cursor()
@ -140,11 +153,12 @@ class OnionrUser:
for result in c.execute("SELECT * FROM myForwardKeys where peer=?", command): for result in c.execute("SELECT * FROM myForwardKeys where peer=?", command):
keyList.append((result[1], result[2])) keyList.append((result[1], result[2]))
if len(keyList) == 0: if len(keyList) == 0:
self.generateForwardKey() if genNew:
keyList = self.getGeneratedForwardKeys() self.generateForwardKey()
keyList = self.getGeneratedForwardKeys()
return list(keyList) return list(keyList)
def addForwardKey(self, newKey, expire=432000): def addForwardKey(self, newKey, expire=604800):
if not self._core._utils.validatePubKey(newKey): if not self._core._utils.validatePubKey(newKey):
raise onionrexceptions.InvalidPubkey raise onionrexceptions.InvalidPubkey
# Add a forward secrecy key for the peer # Add a forward secrecy key for the peer
@ -152,7 +166,7 @@ class OnionrUser:
c = conn.cursor() c = conn.cursor()
# Prepare the insert # Prepare the insert
time = self._core._utils.getEpoch() time = self._core._utils.getEpoch()
command = (self.publicKey, newKey, time, expire) command = (self.publicKey, newKey, time, time + expire)
c.execute("INSERT INTO forwardKeys VALUES(?, ?, ?, ?);", command) c.execute("INSERT INTO forwardKeys VALUES(?, ?, ?, ?);", command)

View File

@ -263,14 +263,19 @@ class OnionrUtils:
''' '''
myBlock = Block(blockHash, self._core) myBlock = Block(blockHash, self._core)
if myBlock.isEncrypted: if myBlock.isEncrypted:
#pass
logger.warn(myBlock.decrypt()) logger.warn(myBlock.decrypt())
if (myBlock.isEncrypted and myBlock.decrypted) or (not myBlock.isEncrypted): if (myBlock.isEncrypted and myBlock.decrypted) or (not myBlock.isEncrypted):
blockType = myBlock.getMetadata('type') # we would use myBlock.getType() here, but it is bugged with encrypted blocks blockType = myBlock.getMetadata('type') # we would use myBlock.getType() here, but it is bugged with encrypted blocks
signer = self.bytesToStr(myBlock.signer) signer = self.bytesToStr(myBlock.signer)
valid = myBlock.verifySig() valid = myBlock.verifySig()
logger.info('Checking for fs key')
if myBlock.getMetadata('newFSKey') is not None: if myBlock.getMetadata('newFSKey') is not None:
onionrusers.OnionrUser(self._core, signer).addForwardKey(myBlock.getMetadata('newFSKey')) onionrusers.OnionrUser(self._core, signer).addForwardKey(myBlock.getMetadata('newFSKey'))
else:
logger.warn('FS not used for this encrypted block')
logger.info(myBlock.bmetadata)
try: try:
if len(blockType) <= 10: if len(blockType) <= 10: