* bumped nacl and unpaddedbase32 verison
* added/improved support for unpaddedbase32 keys * greatly improved home UI and mail * deniable blocks shouldnt use forward secrecy anymore * dont add yourself as a contact
This commit is contained in:
parent
cb2e803ae8
commit
8082570b7f
18 changed files with 117 additions and 55 deletions
|
@ -27,5 +27,5 @@ def insert_deniable_block(comm_inst):
|
|||
# This assumes on the libsodium primitives to have key-privacy
|
||||
fakePeer = onionrvalues.DENIABLE_PEER_ADDRESS
|
||||
data = secrets.token_hex(secrets.randbelow(1024) + 1)
|
||||
comm_inst._core.insertBlock(data, header='pm', encryptType='asym', asymPeer=fakePeer, meta={'subject': 'foo'})
|
||||
comm_inst._core.insertBlock(data, header='pm', encryptType='asym', asymPeer=fakePeer, disableForward=True, meta={'subject': 'foo'})
|
||||
comm_inst.decrementThreadCount('insert_deniable_block')
|
|
@ -128,7 +128,8 @@ class Core:
|
|||
'''
|
||||
Adds a public key to the key database (misleading function name)
|
||||
'''
|
||||
assert peerID not in self.listPeers()
|
||||
if peerID in self.listPeers() or peerID == self._crypto.pubKey:
|
||||
raise ValueError("specified id is already known")
|
||||
|
||||
# This function simply adds a peer to the DB
|
||||
if not self._utils.validatePubKey(peerID):
|
||||
|
@ -776,7 +777,11 @@ class Core:
|
|||
data = self._crypto.pubKeyEncrypt(data, asymPeer, encodedData=True).decode()
|
||||
signature = self._crypto.pubKeyEncrypt(signature, asymPeer, encodedData=True).decode()
|
||||
signer = self._crypto.pubKeyEncrypt(signer, asymPeer, encodedData=True).decode()
|
||||
onionrusers.OnionrUser(self, asymPeer, saveUser=True)
|
||||
try:
|
||||
onionrusers.OnionrUser(self, asymPeer, saveUser=True)
|
||||
except ValueError:
|
||||
# if peer is already known
|
||||
pass
|
||||
else:
|
||||
raise onionrexceptions.InvalidPubkey(asymPeer + ' is not a valid base32 encoded ed25519 key')
|
||||
|
||||
|
|
|
@ -26,7 +26,8 @@ friends = Blueprint('friends', __name__)
|
|||
@friends.route('/friends/list')
|
||||
def list_friends():
|
||||
pubkey_list = {}
|
||||
friend_list = contactmanager.ContactManager.list_friends(core.Core())
|
||||
c = core.Core()
|
||||
friend_list = contactmanager.ContactManager.list_friends(c)
|
||||
for friend in friend_list:
|
||||
pubkey_list[friend.publicKey] = {'name': friend.get_info('name')}
|
||||
return json.dumps(pubkey_list)
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
import sys, getpass
|
||||
import logger, onionrexceptions
|
||||
from onionrusers import onionrusers, contactmanager
|
||||
import unpaddedbase32
|
||||
def add_ID(o_inst):
|
||||
try:
|
||||
sys.argv[2]
|
||||
|
@ -50,6 +51,7 @@ def add_ID(o_inst):
|
|||
def change_ID(o_inst):
|
||||
try:
|
||||
key = sys.argv[2]
|
||||
key = unpaddedbase32.repad(key.encode()).decode()
|
||||
except IndexError:
|
||||
logger.warn('Specify pubkey to use')
|
||||
else:
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
'''
|
||||
import os, binascii, base64, hashlib, time, sys, hmac, secrets
|
||||
import nacl.signing, nacl.encoding, nacl.public, nacl.hash, nacl.pwhash, nacl.utils, nacl.secret
|
||||
import unpaddedbase32
|
||||
import logger, onionrproofs
|
||||
import onionrexceptions, keymanager, core
|
||||
import config
|
||||
|
@ -93,6 +94,7 @@ class OnionrCrypto:
|
|||
|
||||
def pubKeyEncrypt(self, data, pubkey, encodedData=False):
|
||||
'''Encrypt to a public key (Curve25519, taken from base32 Ed25519 pubkey)'''
|
||||
pubkey = unpaddedbase32.repad(self._core._utils.strToBytes(pubkey))
|
||||
retVal = ''
|
||||
box = None
|
||||
data = self._core._utils.strToBytes(data)
|
||||
|
@ -129,7 +131,7 @@ class OnionrCrypto:
|
|||
return decrypted
|
||||
|
||||
def symmetricEncrypt(self, data, key, encodedKey=False, returnEncoded=True):
|
||||
'''Encrypt data to a 32-byte key (Salsa20-Poly1305 MAC)'''
|
||||
'''Encrypt data with a 32-byte key (Salsa20-Poly1305 MAC)'''
|
||||
if encodedKey:
|
||||
encoding = nacl.encoding.Base64Encoder
|
||||
else:
|
||||
|
@ -199,7 +201,7 @@ class OnionrCrypto:
|
|||
if pubkey == '':
|
||||
pubkey = self.pubKey
|
||||
prev = ''
|
||||
pubkey = pubkey.encode()
|
||||
pubkey = self._core._utils.strToBytes(pubkey)
|
||||
for i in range(self.HASH_ID_ROUNDS):
|
||||
try:
|
||||
prev = prev.encode()
|
||||
|
|
|
@ -18,10 +18,12 @@
|
|||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
'''
|
||||
import os, json, onionrexceptions
|
||||
import unpaddedbase32
|
||||
from onionrusers import onionrusers
|
||||
|
||||
class ContactManager(onionrusers.OnionrUser):
|
||||
def __init__(self, coreInst, publicKey, saveUser=False, recordExpireSeconds=5):
|
||||
publicKey = unpaddedbase32.repad(coreInst._utils.strToBytes(publicKey)).decode()
|
||||
super(ContactManager, self).__init__(coreInst, publicKey, saveUser=saveUser)
|
||||
self.dataDir = coreInst.dataDir + '/contacts/'
|
||||
self.dataFile = '%s/contacts/%s.json' % (coreInst.dataDir, publicKey)
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
'''
|
||||
import onionrblockapi, logger, onionrexceptions, json, sqlite3, time
|
||||
import unpaddedbase32
|
||||
import nacl.exceptions
|
||||
|
||||
def deleteExpiredKeys(coreInst):
|
||||
|
@ -55,8 +56,7 @@ class OnionrUser:
|
|||
Takes an instance of onionr core, a base32 encoded ed25519 public key, and a bool saveUser
|
||||
saveUser determines if we should add a user to our peer database or not.
|
||||
'''
|
||||
if ' ' in coreInst._utils.bytesToStr(publicKey).strip():
|
||||
publicKey = coreInst._utils.convertHumanReadableID(publicKey)
|
||||
publicKey = unpaddedbase32.repad(coreInst._utils.strToBytes(publicKey)).decode()
|
||||
|
||||
self.trust = 0
|
||||
self._core = coreInst
|
||||
|
@ -190,6 +190,7 @@ class OnionrUser:
|
|||
return list(keyList)
|
||||
|
||||
def addForwardKey(self, newKey, expire=DEFAULT_KEY_EXPIRE):
|
||||
newKey = self._core._utils.bytesToStr(unpaddedbase32.repad(self._core._utils.strToBytes(newKey)))
|
||||
if not self._core._utils.validatePubKey(newKey):
|
||||
# Do not add if something went wrong with the key
|
||||
raise onionrexceptions.InvalidPubkey(newKey)
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
import sys, os, sqlite3, binascii, time, base64, json, glob, shutil, math, re, urllib.parse, string
|
||||
import requests
|
||||
import nacl.signing, nacl.encoding
|
||||
import unpaddedbase32
|
||||
from onionrblockapi import Block
|
||||
import onionrexceptions, config, logger
|
||||
from onionr import API_VERSION
|
||||
|
@ -319,9 +320,12 @@ class OnionrUtils:
|
|||
'''
|
||||
Validate if a string is a valid base32 encoded Ed25519 key
|
||||
'''
|
||||
retVal = False
|
||||
if type(key) is type(None):
|
||||
return False
|
||||
# Accept keys that have no = padding
|
||||
key = unpaddedbase32.repad(self.strToBytes(key))
|
||||
|
||||
retVal = False
|
||||
try:
|
||||
nacl.signing.SigningKey(seed=key, encoder=nacl.encoding.Base32Encoder)
|
||||
except nacl.exceptions.ValueError:
|
||||
|
|
|
@ -113,4 +113,8 @@ input{
|
|||
color: black;
|
||||
font-size: 1.5em;
|
||||
width: 10%;
|
||||
}
|
||||
|
||||
.content{
|
||||
min-height: 1000px;
|
||||
}
|
|
@ -58,9 +58,9 @@ function openReply(bHash, quote, subject){
|
|||
// Add quoted reply
|
||||
var splitQuotes = quote.split('\n')
|
||||
for (var x = 0; x < splitQuotes.length; x++){
|
||||
splitQuotes[x] = '>' + splitQuotes[x]
|
||||
splitQuotes[x] = '> ' + splitQuotes[x]
|
||||
}
|
||||
quote = '\n' + splitQuotes.join('\n')
|
||||
quote = '\n' + key.substring(0, 12) + ' wrote:' + '\n' + splitQuotes.join('\n')
|
||||
document.getElementById('draftText').value = quote
|
||||
setActiveTab('send message')
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ function openThread(bHash, sender, date, sigBool, pubkey, subjectLine){
|
|||
var sigMsg = 'signature'
|
||||
|
||||
// show add unknown contact button if peer is unknown but still has pubkey
|
||||
if (sender == pubkey){
|
||||
if (sender === pubkey && sender !== myPub){
|
||||
addUnknownContact.style.display = 'inline'
|
||||
}
|
||||
|
||||
|
|
|
@ -54,6 +54,11 @@ sendForm.onsubmit = function(){
|
|||
return false
|
||||
}
|
||||
}
|
||||
sendMail(to.value, messageContent.value, subject.value)
|
||||
if (to.value.length !== 56 && to.value.length !== 52){
|
||||
alert('Public key is not valid')
|
||||
}
|
||||
else{
|
||||
sendMail(to.value, messageContent.value, subject.value)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -21,26 +21,26 @@
|
|||
<br><br>
|
||||
<div>🕵️♂️ Current Used Identity: <input class='myPub' type='text' readonly></div>
|
||||
<br>
|
||||
<button id='shutdownNode' class='warnBtn'>Shutdown Node</button> <button id='refreshStats' class='primaryBtn'>Refresh Stats</button>
|
||||
<button id='shutdownNode' class='btn warnBtn'>Shutdown Node</button> <button id='refreshStats' class='btn primaryBtn'>Refresh Stats</button>
|
||||
<br><br>
|
||||
<h1>Onionr Services</h1>
|
||||
<label>Open Site: <input type='text' id='siteViewer' placeholder='Site Hash'> <button id='openSite' class='primaryBtn openSiteBtn'>Open Onionr Site</button></label>
|
||||
<br>
|
||||
<br><br><a class='idLink' href='/mail/'>Mail</a> - <a class='idLink' href='/friends/'>Friend Manager</a> - <a class='idLink' href='/board/'>Boards</a> -
|
||||
<br><br><a class='idLink' href='/mail/'>Mail</a> - <a class='idLink' href='/friends/'>Friend Manager</a> - <a class='idLink' href='/board/'>Circle</a> -
|
||||
<a class='idLink' href='/clandestine/'>Clandestine</a>
|
||||
<br><br><hr>
|
||||
<details class='configArea'>
|
||||
<summary><b>Edit Configuration</b></summary>
|
||||
<br>
|
||||
<p><em>Warning: </em><b>Some values can be dangerous to change. Use caution.</b></p>
|
||||
<p><em>Warning: </em><b>Some values can be dangerous to change.<br><br>Configuration contains sensitive information.</b></p>
|
||||
<br>
|
||||
<textarea class='configEditor'></textarea>
|
||||
<button class='saveConfig successBtn'>Save Config</button>
|
||||
</details>
|
||||
<hr>
|
||||
<h1>Statistics</h1>
|
||||
<p>🔒 Security Level: <span id='securityLevel'></span></p>
|
||||
<p>🕰️ Uptime: <span id='uptime'></span></p>
|
||||
<h2>Connections</h2>
|
||||
<p class='secRequestNotice hidden'>Note: on high security levels, you should have <em>no</em> received requests.</p>
|
||||
<p>🖇️ Last Received Request: <span id='lastIncoming'>None since start</span></p>
|
||||
<p>⬇️ Total Requests Received: <span id='totalRec'>None since start</span></p>
|
||||
<p>🔗 Outgoing Connections:</p>
|
||||
|
|
|
@ -5,4 +5,14 @@
|
|||
|
||||
.saveConfig{
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
|
||||
.idLink{
|
||||
-webkit-touch-callout: none; /* iOS Safari */
|
||||
-webkit-user-select: none; /* Safari */
|
||||
-moz-user-select: none; /* Firefox */
|
||||
-ms-user-select: none; /* Internet Explorer/Edge */
|
||||
user-select: none; /* Non-prefixed version, currently
|
||||
supported by Chrome and Opera */
|
||||
}
|
|
@ -18,10 +18,34 @@
|
|||
*/
|
||||
uptimeDisplay = document.getElementById('uptime')
|
||||
connectedDisplay = document.getElementById('connectedNodes')
|
||||
connectedDisplay.style.maxHeight = '300px'
|
||||
connectedDisplay.style.overflowY = 'scroll'
|
||||
storedBlockDisplay = document.getElementById('storedBlocks')
|
||||
queuedBlockDisplay = document.getElementById('blockQueue')
|
||||
lastIncoming = document.getElementById('lastIncoming')
|
||||
totalRec = document.getElementById('totalRec')
|
||||
securityLevel = document.getElementById('securityLevel')
|
||||
sec_description_str = 'unknown'
|
||||
|
||||
function showSecStatNotice(){
|
||||
var secWarnEls = document.getElementsByClassName('secRequestNotice')
|
||||
for (el = 0; el < secWarnEls.length; el++){
|
||||
secWarnEls[el].style.display = 'block'
|
||||
}
|
||||
}
|
||||
|
||||
switch (httpGet('/config/get/general.security_level')){
|
||||
case "0":
|
||||
sec_description_str = 'normal'
|
||||
break;
|
||||
case "1":
|
||||
sec_description_str = 'high'
|
||||
break;
|
||||
}
|
||||
|
||||
if (sec_description_str !== 'normal'){
|
||||
showSecStatNotice()
|
||||
}
|
||||
|
||||
function getStats(){
|
||||
stats = JSON.parse(httpGet('getstats', webpass))
|
||||
|
@ -29,6 +53,7 @@ function getStats(){
|
|||
connectedDisplay.innerText = stats['connectedNodes']
|
||||
storedBlockDisplay.innerText = stats['blockCount']
|
||||
queuedBlockDisplay.innerText = stats['blockQueueCount']
|
||||
securityLevel.innerText = sec_description_str
|
||||
totalRec.innerText = httpGet('/hitcount')
|
||||
var lastConnect = httpGet('/lastconnect')
|
||||
if (lastConnect > 0){
|
||||
|
|
|
@ -178,8 +178,16 @@ body{
|
|||
background-color:#396BAC;
|
||||
}
|
||||
|
||||
.btn:hover{
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.openSiteBtn{
|
||||
padding: 5px;
|
||||
border: 1px solid black;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.hidden{
|
||||
display: none;
|
||||
}
|
||||
|
|
|
@ -29,11 +29,13 @@ class OnionrValidations(unittest.TestCase):
|
|||
|
||||
def test_pubkey_validator(self):
|
||||
# Test ed25519 public key validity
|
||||
valid = 'JZ5VE72GUS3C7BOHDRIYZX4B5U5EJMCMLKHLYCVBQQF3UKHYIRRQ===='
|
||||
valids = ['JZ5VE72GUS3C7BOHDRIYZX4B5U5EJMCMLKHLYCVBQQF3UKHYIRRQ====', 'JZ5VE72GUS3C7BOHDRIYZX4B5U5EJMCMLKHLYCVBQQF3UKHYIRRQ']
|
||||
invalid = [None, '', ' ', 'dfsg', '\n', 'JZ5VE72GUS3C7BOHDRIYZX4B5U5EJMCMLKHLYCVBQQF3UKHYIR$Q====']
|
||||
c = core.Core()
|
||||
print('testing', valid)
|
||||
self.assertTrue(c._utils.validatePubKey(valid))
|
||||
|
||||
for valid in valids:
|
||||
print('testing', valid)
|
||||
self.assertTrue(c._utils.validatePubKey(valid))
|
||||
|
||||
for x in invalid:
|
||||
#print('testing', x)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue