* 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
master
Kevin Froman 2019-06-19 01:57:13 -05:00
parent cb2e803ae8
commit 8082570b7f
18 changed files with 117 additions and 55 deletions

View File

@ -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')

View File

@ -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')

View File

@ -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)

View File

@ -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:

View File

@ -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()

View File

@ -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)

View File

@ -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)

View File

@ -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:

View File

@ -113,4 +113,8 @@ input{
color: black;
font-size: 1.5em;
width: 10%;
}
.content{
min-height: 1000px;
}

View File

@ -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'
}

View File

@ -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
}

View File

@ -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>

View File

@ -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 */
}

View File

@ -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){

View File

@ -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;
}

View File

@ -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)

View File

@ -1,9 +1,10 @@
urllib3==1.24.2
requests==2.21.0
PyNaCl==1.2.1
PyNaCl==1.3.0
gevent==1.3.6
Flask==1.0.2
PySocks==1.6.8
stem==1.7.1
deadsimplekv==0.1.1
unpaddedbase32==0.1.0
jinja2==2.10.1

View File

@ -2,7 +2,7 @@
# This file is autogenerated by pip-compile
# To update, run:
#
# pip-compile --generate-hashes --output-file requirements.txt requirements.in
# pip-compile --generate-hashes --output-file=requirements.txt requirements.in
#
certifi==2018.11.29 \
--hash=sha256:47f9c83ef4c0c621eaef743f133f09fa8a74a9b75f037e8624f83bd1b6626cb7 \
@ -140,38 +140,26 @@ markupsafe==1.1.1 \
pycparser==2.19 \
--hash=sha256:a988718abfad80b6b157acce7bf130a30876d27603738ac39f140993246b25b3 \
# via cffi
pynacl==1.2.1 \
--hash=sha256:04e30e5bdeeb2d5b34107f28cd2f5bbfdc6c616f3be88fc6f53582ff1669eeca \
--hash=sha256:0bfa0d94d2be6874e40f896e0a67e290749151e7de767c5aefbad1121cad7512 \
--hash=sha256:11aa4e141b2456ce5cecc19c130e970793fa3a2c2e6fbb8ad65b28f35aa9e6b6 \
--hash=sha256:13bdc1fe084ff9ac7653ae5a924cae03bf4bb07c6667c9eb5b6eb3c570220776 \
--hash=sha256:14339dc233e7a9dda80a3800e64e7ff89d0878ba23360eea24f1af1b13772cac \
--hash=sha256:1d33e775fab3f383167afb20b9927aaf4961b953d76eeb271a5703a6d756b65b \
--hash=sha256:2a42b2399d0428619e58dac7734838102d35f6dcdee149e0088823629bf99fbb \
--hash=sha256:2dce05ac8b3c37b9e2f65eab56c544885607394753e9613fd159d5e2045c2d98 \
--hash=sha256:63cfccdc6217edcaa48369191ae4dca0c390af3c74f23c619e954973035948cd \
--hash=sha256:6453b0dae593163ffc6db6f9c9c1597d35c650598e2c39c0590d1757207a1ac2 \
--hash=sha256:73a5a96fb5fbf2215beee2353a128d382dbca83f5341f0d3c750877a236569ef \
--hash=sha256:8abb4ef79161a5f58848b30ab6fb98d8c466da21fdd65558ce1d7afc02c70b5f \
--hash=sha256:8ac1167195b32a8755de06efd5b2d2fe76fc864517dab66aaf65662cc59e1988 \
--hash=sha256:8f505f42f659012794414fa57c498404e64db78f1d98dfd40e318c569f3c783b \
--hash=sha256:9c8a06556918ee8e3ab48c65574f318f5a0a4d31437fc135da7ee9d4f9080415 \
--hash=sha256:a1e25fc5650cf64f01c9e435033e53a4aca9de30eb9929d099f3bb078e18f8f2 \
--hash=sha256:be71cd5fce04061e1f3d39597f93619c80cdd3558a6c9ba99a546f144a8d8101 \
--hash=sha256:c5b1a7a680218dee9da0f1b5e24072c46b3c275d35712bc1d505b85bb03441c0 \
--hash=sha256:cb785db1a9468841a1265c9215c60fe5d7af2fb1b209e3316a152704607fc582 \
--hash=sha256:cf6877124ae6a0698404e169b3ba534542cfbc43f939d46b927d956daf0a373a \
--hash=sha256:d0eb5b2795b7ee2cbcfcadacbe95a13afbda048a262bd369da9904fecb568975 \
--hash=sha256:d3a934e2b9f20abac009d5b6951067cfb5486889cb913192b4d8288b216842f1 \
--hash=sha256:d795f506bcc9463efb5ebb0f65ed77921dcc9e0a50499dedd89f208445de9ecb \
--hash=sha256:d8aaf7e5d6b0e0ef7d6dbf7abeb75085713d0100b4eb1a4e4e857de76d77ac45 \
--hash=sha256:de2aaca8386cf4d70f1796352f2346f48ddb0bed61dc43a3ce773ba12e064031 \
--hash=sha256:e0d38fa0a75f65f556fb912f2c6790d1fa29b7dd27a1d9cc5591b281321eaaa9 \
--hash=sha256:eb2acabbd487a46b38540a819ef67e477a674481f84a82a7ba2234b9ba46f752 \
--hash=sha256:eeee629828d0eb4f6d98ac41e9a3a6461d114d1d0aa111a8931c049359298da0 \
--hash=sha256:f5836463a3c0cca300295b229b6c7003c415a9d11f8f9288ddbd728e2746524c \
--hash=sha256:f5ce9e26d25eb0b2d96f3ef0ad70e1d3ae89b5d60255c462252a3e456a48c053 \
--hash=sha256:fabf73d5d0286f9e078774f3435601d2735c94ce9e514ac4fb945701edead7e4
pynacl==1.3.0 \
--hash=sha256:05c26f93964373fc0abe332676cb6735f0ecad27711035b9472751faa8521255 \
--hash=sha256:0c6100edd16fefd1557da078c7a31e7b7d7a52ce39fdca2bec29d4f7b6e7600c \
--hash=sha256:0d0a8171a68edf51add1e73d2159c4bc19fc0718e79dec51166e940856c2f28e \
--hash=sha256:1c780712b206317a746ace34c209b8c29dbfd841dfbc02aa27f2084dd3db77ae \
--hash=sha256:2424c8b9f41aa65bbdbd7a64e73a7450ebb4aa9ddedc6a081e7afcc4c97f7621 \
--hash=sha256:2d23c04e8d709444220557ae48ed01f3f1086439f12dbf11976e849a4926db56 \
--hash=sha256:30f36a9c70450c7878053fa1344aca0145fd47d845270b43a7ee9192a051bf39 \
--hash=sha256:37aa336a317209f1bb099ad177fef0da45be36a2aa664507c5d72015f956c310 \
--hash=sha256:4943decfc5b905748f0756fdd99d4f9498d7064815c4cf3643820c9028b711d1 \
--hash=sha256:57ef38a65056e7800859e5ba9e6091053cd06e1038983016effaffe0efcd594a \
--hash=sha256:5bd61e9b44c543016ce1f6aef48606280e45f892a928ca7068fba30021e9b786 \
--hash=sha256:6482d3017a0c0327a49dddc8bd1074cc730d45db2ccb09c3bac1f8f32d1eb61b \
--hash=sha256:7d3ce02c0784b7cbcc771a2da6ea51f87e8716004512493a2b69016326301c3b \
--hash=sha256:a14e499c0f5955dcc3991f785f3f8e2130ed504fa3a7f44009ff458ad6bdd17f \
--hash=sha256:a39f54ccbcd2757d1d63b0ec00a00980c0b382c62865b61a505163943624ab20 \
--hash=sha256:aabb0c5232910a20eec8563503c153a8e78bbf5459490c49ab31f6adf3f3a415 \
--hash=sha256:bd4ecb473a96ad0f90c20acba4f0bf0df91a4e03a1f4dd6a4bdc9ca75aa3a715 \
--hash=sha256:e2da3c13307eac601f3de04887624939aca8ee3c9488a0bb0eca4fb9401fc6b1 \
--hash=sha256:f67814c38162f4deb31f68d590771a29d5ae3b1bd64b75cf232308e5c74777e0
pysocks==1.6.8 \
--hash=sha256:3fe52c55890a248676fd69dc9e3c4e811718b777834bcaab7a8125cf9deac672
requests==2.21.0 \
@ -183,6 +171,8 @@ six==1.12.0 \
# via pynacl
stem==1.7.1 \
--hash=sha256:c9eaf3116cb60c15995cbd3dec3a5cbc50e9bb6e062c4d6d42201e566f498ca2
unpaddedbase32==0.1.0 \
--hash=sha256:5e4143fcaf77c9c6b4f60d18301c7570f0dac561dcf9b9aed8b5ba6ead7f218c
urllib3==1.24.2 \
--hash=sha256:4c291ca23bbb55c76518905869ef34bdd5f0e46af7afe6861e8375643ffee1a0 \
--hash=sha256:9a247273df709c4fedb38c711e44292304f73f39ab01beda9f6b9fc375669ac3