* onionrblockapi supports pubkey encryption now
* can now read messages in mail pluginmaster
parent
7390945ebf
commit
2a4cef68f8
|
@ -627,13 +627,16 @@ class Core:
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def getBlocksByType(self, blockType):
|
def getBlocksByType(self, blockType, orderDate=True):
|
||||||
'''
|
'''
|
||||||
Returns a list of blocks by the type
|
Returns a list of blocks by the type
|
||||||
'''
|
'''
|
||||||
conn = sqlite3.connect(self.blockDB)
|
conn = sqlite3.connect(self.blockDB)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
execute = 'SELECT hash FROM hashes WHERE dataType=?;'
|
if orderDate:
|
||||||
|
execute = 'SELECT hash FROM hashes WHERE dataType=? ORDER BY dateReceived;'
|
||||||
|
else:
|
||||||
|
execute = 'SELECT hash FROM hashes WHERE dataType=?;'
|
||||||
args = (blockType,)
|
args = (blockType,)
|
||||||
rows = list()
|
rows = list()
|
||||||
for row in c.execute(execute, args):
|
for row in c.execute(execute, args):
|
||||||
|
@ -733,9 +736,10 @@ class Core:
|
||||||
signer = self._crypto.symmetricEncrypt(signer, key=symKey, returnEncoded=True).decode()
|
signer = self._crypto.symmetricEncrypt(signer, key=symKey, returnEncoded=True).decode()
|
||||||
elif encryptType == 'asym':
|
elif encryptType == 'asym':
|
||||||
if self._utils.validatePubKey(asymPeer):
|
if self._utils.validatePubKey(asymPeer):
|
||||||
jsonMeta = self._crypto.pubKeyEncrypt(jsonMeta, asymPeer, encodedData=True).decode()
|
jsonMeta = self._crypto.pubKeyEncrypt(jsonMeta, asymPeer, encodedData=True, anonymous=True).decode()
|
||||||
data = self._crypto.pubKeyEncrypt(data, asymPeer, encodedData=True).decode()
|
data = self._crypto.pubKeyEncrypt(data, asymPeer, encodedData=True, anonymous=True).decode()
|
||||||
signature = self._crypto.pubKeyEncrypt(signature, asymPeer, encodedData=True).decode()
|
signature = self._crypto.pubKeyEncrypt(signature, asymPeer, encodedData=True, anonymous=True).decode()
|
||||||
|
signer = self._crypto.pubKeyEncrypt(signer, asymPeer, encodedData=True, anonymous=True).decode()
|
||||||
else:
|
else:
|
||||||
raise onionrexceptions.InvalidPubkey(asymPeer + ' is not a valid base32 encoded ed25519 key')
|
raise onionrexceptions.InvalidPubkey(asymPeer + ' is not a valid base32 encoded ed25519 key')
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
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 core as onionrcore, logger, config, onionrexceptions
|
import core as onionrcore, logger, config, onionrexceptions, nacl.exceptions
|
||||||
import json, os, sys, datetime, base64
|
import json, os, sys, datetime, base64
|
||||||
|
|
||||||
class Block:
|
class Block:
|
||||||
|
@ -50,6 +50,9 @@ class Block:
|
||||||
self.bheader = {}
|
self.bheader = {}
|
||||||
self.bmetadata = {}
|
self.bmetadata = {}
|
||||||
self.isEncrypted = False
|
self.isEncrypted = False
|
||||||
|
self.decrypted = False
|
||||||
|
self.signer = None
|
||||||
|
self.validSig = False
|
||||||
|
|
||||||
# handle arguments
|
# handle arguments
|
||||||
if self.getCore() is None:
|
if self.getCore() is None:
|
||||||
|
@ -69,11 +72,39 @@ class Block:
|
||||||
|
|
||||||
def decrypt(self, anonymous=True, encodedData=True):
|
def decrypt(self, anonymous=True, encodedData=True):
|
||||||
'''Decrypt a block, loading decrypted data into their vars'''
|
'''Decrypt a block, loading decrypted data into their vars'''
|
||||||
|
if self.decrypted:
|
||||||
|
return True
|
||||||
|
retData = False
|
||||||
|
core = self.getCore()
|
||||||
# decrypt data
|
# decrypt data
|
||||||
self.getCore()._crypto.pubKeyDecrypt(self.bcontent, anonymous=anonymous, encodedData=encodedData)
|
if self.getHeader('encryptType') == 'asym':
|
||||||
|
try:
|
||||||
|
self.bcontent = core._crypto.pubKeyDecrypt(self.bcontent, anonymous=anonymous, encodedData=encodedData)
|
||||||
|
self.bmetadata = json.loads(core._crypto.pubKeyDecrypt(self.bmetadata, anonymous=anonymous, encodedData=encodedData))
|
||||||
|
self.signature = core._crypto.pubKeyDecrypt(self.signature, anonymous=anonymous, encodedData=encodedData)
|
||||||
|
self.signer = core._crypto.pubKeyDecrypt(self.signer, anonymous=anonymous, encodedData=encodedData)
|
||||||
|
self.signedData = json.dumps(self.bmetadata) + self.bcontent.decode()
|
||||||
|
except nacl.exceptions.CryptoError:
|
||||||
|
pass
|
||||||
|
#logger.debug('Could not decrypt block. Either invalid key or corrupted data')
|
||||||
|
else:
|
||||||
|
retData = True
|
||||||
|
self.decrypted = True
|
||||||
|
else:
|
||||||
|
logger.warn('symmetric decryption is not yet supported by this API')
|
||||||
|
return retData
|
||||||
|
|
||||||
|
def verifySig(self):
|
||||||
|
'''Verify if a block's signature is signed by its claimed signer'''
|
||||||
|
core = self.getCore()
|
||||||
|
|
||||||
|
if core._crypto.edVerify(data=self.signedData, key=self.signer, sig=self.signature, encodedData=True):
|
||||||
|
self.validSig = True
|
||||||
|
print('ded')
|
||||||
|
else:
|
||||||
|
self.validSig = False
|
||||||
|
return self.validSig
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
def update(self, data = None, file = None):
|
def update(self, data = None, file = None):
|
||||||
'''
|
'''
|
||||||
|
@ -133,8 +164,11 @@ class Block:
|
||||||
self.parent = self.getMetadata('parent', None)
|
self.parent = self.getMetadata('parent', None)
|
||||||
self.btype = self.getMetadata('type', None)
|
self.btype = self.getMetadata('type', None)
|
||||||
self.signed = ('sig' in self.getHeader() and self.getHeader('sig') != '')
|
self.signed = ('sig' in self.getHeader() and self.getHeader('sig') != '')
|
||||||
|
# TODO: detect if signer is hash of pubkey or not
|
||||||
|
self.signer = self.getHeader('signer', None)
|
||||||
self.signature = self.getHeader('sig', None)
|
self.signature = self.getHeader('sig', None)
|
||||||
self.signedData = (None if not self.isSigned() else self.getHeader('meta') + '\n' + self.getContent())
|
# signed data is jsonMeta + block content (no linebreak)
|
||||||
|
self.signedData = (None if not self.isSigned() else self.getHeader('meta') + self.getContent())
|
||||||
self.date = self.getCore().getBlockDate(self.getHash())
|
self.date = self.getCore().getBlockDate(self.getHash())
|
||||||
|
|
||||||
if not self.getDate() is None:
|
if not self.getDate() is None:
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
'''
|
'''
|
||||||
|
|
||||||
# Imports some useful libraries
|
# Imports some useful libraries
|
||||||
import logger, config, threading, time, readline
|
import logger, config, threading, time, readline, datetime
|
||||||
from onionrblockapi import Block
|
from onionrblockapi import Block
|
||||||
import onionrexceptions
|
import onionrexceptions
|
||||||
|
|
||||||
|
@ -51,13 +51,53 @@ class OnionrMail:
|
||||||
def inbox(self):
|
def inbox(self):
|
||||||
blockCount = 0
|
blockCount = 0
|
||||||
pmBlockMap = {}
|
pmBlockMap = {}
|
||||||
|
pmBlocks = {}
|
||||||
|
logger.info('Decrypting messages...')
|
||||||
|
choice = ''
|
||||||
|
|
||||||
print('Private Messages:')
|
# this could use a lot of memory if someone has recieved a lot of messages
|
||||||
|
|
||||||
for blockHash in self.myCore.getBlocksByType('pm'):
|
for blockHash in self.myCore.getBlocksByType('pm'):
|
||||||
blockCount += 1
|
pmBlocks[blockHash] = Block(blockHash, core=self.myCore)
|
||||||
pmBlockMap[blockCount] = blockHash
|
pmBlocks[blockHash].decrypt()
|
||||||
print('%s: %s' % (blockCount, blockHash))
|
|
||||||
|
while choice not in ('-q', 'q', 'quit'):
|
||||||
|
blockCount = 0
|
||||||
|
for blockHash in pmBlocks:
|
||||||
|
if not pmBlocks[blockHash].decrypted:
|
||||||
|
continue
|
||||||
|
blockCount += 1
|
||||||
|
pmBlockMap[blockCount] = blockHash
|
||||||
|
blockDate = pmBlocks[blockHash].getDate().strftime("%m/%d %H:%M")
|
||||||
|
print('%s. %s: %s' % (blockCount, blockDate, blockHash))
|
||||||
|
|
||||||
|
try:
|
||||||
|
choice = logger.readline('Enter a block number, -r to refresh, or -q to stop: ').strip().lower()
|
||||||
|
except (EOFError, KeyboardInterrupt):
|
||||||
|
choice = '-q'
|
||||||
|
|
||||||
|
if choice in ('-q', 'q', 'quit'):
|
||||||
|
continue
|
||||||
|
|
||||||
|
if choice in ('-r', 'r', 'refresh'):
|
||||||
|
# dirty hack
|
||||||
|
self.inbox()
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
choice = int(choice)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
pmBlockMap[choice]
|
||||||
|
readBlock = pmBlocks[pmBlockMap[choice]]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
readBlock.verifySig()
|
||||||
|
print('Message recieved from', readBlock.signer)
|
||||||
|
print('Valid signature:', readBlock.validSig)
|
||||||
|
print(self.myCore._utils.escapeAnsi(readBlock.bcontent.decode()))
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue