Compare commits
No commits in common. "2c9836c54f5ad9a146ad6c245fce0d468e74daac" and "cdeaa403afe0d5f3c1e8979277fb9c41b0832b76" have entirely different histories.
2c9836c54f
...
cdeaa403af
1
src/coredb/__init__.py
Normal file
1
src/coredb/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
from . import keydb
|
9
src/coredb/dbfiles.py
Normal file
9
src/coredb/dbfiles.py
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
from utils import identifyhome
|
||||||
|
import filepaths
|
||||||
|
home = identifyhome.identify_home()
|
||||||
|
if not home.endswith('/'): home += '/'
|
||||||
|
|
||||||
|
address_info_db = '%saddress.db' % (home,)
|
||||||
|
user_id_info_db = '%susers.db' % (home,)
|
||||||
|
forward_keys_db = '%sforward-keys.db' % (home,)
|
||||||
|
blacklist_db = '%sblacklist.db' % (home,)
|
1
src/coredb/keydb/__init__.py
Normal file
1
src/coredb/keydb/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
from . import addkeys, listkeys, removekeys, userinfo
|
55
src/coredb/keydb/addkeys.py
Normal file
55
src/coredb/keydb/addkeys.py
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
"""Onionr - Private P2P Communication.
|
||||||
|
|
||||||
|
add user keys or transport addresses
|
||||||
|
"""
|
||||||
|
import sqlite3
|
||||||
|
from onionrutils import stringvalidators
|
||||||
|
from . import listkeys
|
||||||
|
from .. import dbfiles
|
||||||
|
import onionrcrypto
|
||||||
|
import onionrvalues
|
||||||
|
"""
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def add_pub_key(peerID, name=''):
|
||||||
|
"""Add a public key to the key database (misleading function name)."""
|
||||||
|
if peerID in listkeys.list_pub_keys() or peerID == onionrcrypto.pub_key:
|
||||||
|
raise ValueError("specified id is already known")
|
||||||
|
|
||||||
|
# This function simply adds a peer to the DB
|
||||||
|
if not stringvalidators.validate_pub_key(peerID):
|
||||||
|
return False
|
||||||
|
|
||||||
|
conn = sqlite3.connect(dbfiles.user_id_info_db, timeout=onionrvalues.DATABASE_LOCK_TIMEOUT)
|
||||||
|
hashID = ""
|
||||||
|
c = conn.cursor()
|
||||||
|
t = (peerID, name, 'unknown', hashID, 0)
|
||||||
|
|
||||||
|
for i in c.execute("SELECT * FROM peers WHERE id = ?;", (peerID,)):
|
||||||
|
try:
|
||||||
|
if i[0] == peerID:
|
||||||
|
conn.close()
|
||||||
|
return False
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
except IndexError:
|
||||||
|
pass
|
||||||
|
c.execute('INSERT INTO peers (id, name, dateSeen, hashID, trust) VALUES(?, ?, ?, ?, ?);', t)
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
63
src/coredb/keydb/listkeys.py
Normal file
63
src/coredb/keydb/listkeys.py
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
"""
|
||||||
|
Onionr - Private P2P Communication
|
||||||
|
|
||||||
|
get lists for user keys
|
||||||
|
"""
|
||||||
|
import sqlite3
|
||||||
|
import logger
|
||||||
|
from onionrutils import epoch
|
||||||
|
import onionrvalues
|
||||||
|
from .. import dbfiles
|
||||||
|
from . import userinfo
|
||||||
|
"""
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def list_pub_keys(randomOrder=True, getPow=False, trust=0):
|
||||||
|
"""
|
||||||
|
Return a list of public keys (misleading function name)
|
||||||
|
|
||||||
|
randomOrder determines if the list should be in a random order
|
||||||
|
trust sets the minimum trust to list
|
||||||
|
"""
|
||||||
|
conn = sqlite3.connect(dbfiles.user_id_info_db, timeout=onionrvalues.DATABASE_LOCK_TIMEOUT)
|
||||||
|
c = conn.cursor()
|
||||||
|
|
||||||
|
payload = ''
|
||||||
|
|
||||||
|
if trust not in (0, 1, 2):
|
||||||
|
logger.error('Tried to select invalid trust.')
|
||||||
|
return
|
||||||
|
|
||||||
|
if randomOrder:
|
||||||
|
payload = 'SELECT * FROM peers WHERE trust >= ? ORDER BY RANDOM();'
|
||||||
|
else:
|
||||||
|
payload = 'SELECT * FROM peers WHERE trust >= ?;'
|
||||||
|
|
||||||
|
peer_list = []
|
||||||
|
|
||||||
|
for i in c.execute(payload, (trust,)):
|
||||||
|
try:
|
||||||
|
if len(i[0]) != 0:
|
||||||
|
if getPow:
|
||||||
|
peer_list.append(i[0] + '-' + i[1])
|
||||||
|
else:
|
||||||
|
peer_list.append(i[0])
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
return peer_list
|
43
src/coredb/keydb/removekeys.py
Normal file
43
src/coredb/keydb/removekeys.py
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
"""
|
||||||
|
Onionr - Private P2P Communication
|
||||||
|
|
||||||
|
Remove a transport address but don't ban them
|
||||||
|
"""
|
||||||
|
import sqlite3
|
||||||
|
from onionrplugins import onionrevents as events
|
||||||
|
from onionrutils import stringvalidators
|
||||||
|
from onionrutils import mnemonickeys
|
||||||
|
from .. import dbfiles
|
||||||
|
import onionrvalues
|
||||||
|
"""
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def remove_user(pubkey: str)->bool:
|
||||||
|
"""Remove a user from the user database"""
|
||||||
|
pubkey = mnemonickeys.get_base32(pubkey)
|
||||||
|
if stringvalidators.validate_pub_key(pubkey):
|
||||||
|
conn = sqlite3.connect(
|
||||||
|
dbfiles.user_id_info_db,
|
||||||
|
timeout=onionrvalues.DATABASE_LOCK_TIMEOUT)
|
||||||
|
c = conn.cursor()
|
||||||
|
t = (pubkey,)
|
||||||
|
c.execute('Delete from peers where id=?;', t)
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
74
src/coredb/keydb/userinfo.py
Normal file
74
src/coredb/keydb/userinfo.py
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
"""
|
||||||
|
Onionr - Private P2P Communication
|
||||||
|
|
||||||
|
get or set information about a user id
|
||||||
|
"""
|
||||||
|
import sqlite3
|
||||||
|
from .. import dbfiles
|
||||||
|
import onionrvalues
|
||||||
|
|
||||||
|
"""
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def get_user_info(peer, info):
|
||||||
|
"""
|
||||||
|
Get info about a peer from their database entry
|
||||||
|
|
||||||
|
id text 0
|
||||||
|
name text, 1
|
||||||
|
adders text, 2
|
||||||
|
dateSeen not null, 3
|
||||||
|
trust int 4
|
||||||
|
hashID text 5
|
||||||
|
"""
|
||||||
|
conn = sqlite3.connect(dbfiles.user_id_info_db, timeout=onionrvalues.DATABASE_LOCK_TIMEOUT)
|
||||||
|
c = conn.cursor()
|
||||||
|
|
||||||
|
command = (peer,)
|
||||||
|
infoNumbers = {'id': 0, 'name': 1, 'adders': 2, 'dateSeen': 3, 'trust': 4, 'hashID': 5}
|
||||||
|
info = infoNumbers[info]
|
||||||
|
iterCount = 0
|
||||||
|
retVal = ''
|
||||||
|
|
||||||
|
for row in c.execute('SELECT * FROM peers WHERE id=?;', command):
|
||||||
|
for i in row:
|
||||||
|
if iterCount == info:
|
||||||
|
retVal = i
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
iterCount += 1
|
||||||
|
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
|
||||||
|
def set_peer_info(peer, key, data):
|
||||||
|
"""
|
||||||
|
Update a peer for a key
|
||||||
|
"""
|
||||||
|
|
||||||
|
conn = sqlite3.connect(dbfiles.user_id_info_db, timeout=onionrvalues.DATABASE_LOCK_TIMEOUT)
|
||||||
|
c = conn.cursor()
|
||||||
|
|
||||||
|
command = (data, peer)
|
||||||
|
|
||||||
|
if key not in ('id', 'name', 'pubkey', 'forwardKey', 'dateSeen', 'trust'):
|
||||||
|
raise ValueError("Got invalid database key when setting peer info")
|
||||||
|
|
||||||
|
c.execute('UPDATE peers SET ' + key + ' = ? WHERE id=?', command)
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
set_user_info = set_peer_info
|
@ -21,6 +21,7 @@ from utils import identifyhome
|
|||||||
import filepaths
|
import filepaths
|
||||||
import onionrvalues
|
import onionrvalues
|
||||||
from onionrutils import cleanup
|
from onionrutils import cleanup
|
||||||
|
from onionrcrypto import getourkeypair
|
||||||
from onionrthreads import add_onionr_thread
|
from onionrthreads import add_onionr_thread
|
||||||
from blockdb.blockcleaner import clean_block_database
|
from blockdb.blockcleaner import clean_block_database
|
||||||
from .. import version
|
from .. import version
|
||||||
@ -51,6 +52,10 @@ def _show_info_messages():
|
|||||||
if onionrvalues.DEVELOPMENT_MODE:
|
if onionrvalues.DEVELOPMENT_MODE:
|
||||||
logger.warn('Development mode enabled', timestamp=False, terminal=True)
|
logger.warn('Development mode enabled', timestamp=False, terminal=True)
|
||||||
|
|
||||||
|
logger.info('Using public key: %s' %
|
||||||
|
(logger.colors.underline +
|
||||||
|
getourkeypair.get_keypair()[0][:52]))
|
||||||
|
|
||||||
|
|
||||||
def daemon():
|
def daemon():
|
||||||
"""Start Onionr's primary threads for communicator, API server, node, and LAN."""
|
"""Start Onionr's primary threads for communicator, API server, node, and LAN."""
|
||||||
@ -85,13 +90,10 @@ def daemon():
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
while True:
|
while True:
|
||||||
# Mainly for things like repls
|
|
||||||
events.event('primary_loop', threaded=False)
|
|
||||||
sleep(60)
|
sleep(60)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
cleanup.delete_run_files()
|
cleanup.delete_run_files()
|
||||||
if security_level >= 2:
|
if security_level >= 2:
|
||||||
filenuke.nuke.clean_tree(identifyhome.identify_home())
|
filenuke.nuke.clean_tree(identifyhome.identify_home())
|
||||||
|
@ -4,7 +4,10 @@ This module defines commands to show stats/details about the local node
|
|||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
import logger
|
import logger
|
||||||
|
from onionrutils import mnemonickeys
|
||||||
from utils import sizeutils, getconsolewidth, identifyhome
|
from utils import sizeutils, getconsolewidth, identifyhome
|
||||||
|
from coredb import keydb
|
||||||
|
import onionrcrypto
|
||||||
import config
|
import config
|
||||||
import onionrvalues
|
import onionrvalues
|
||||||
from filepaths import lock_file
|
from filepaths import lock_file
|
||||||
@ -126,6 +129,8 @@ def show_details():
|
|||||||
"""
|
"""
|
||||||
details = {
|
details = {
|
||||||
'Data directory': identifyhome.identify_home(),
|
'Data directory': identifyhome.identify_home(),
|
||||||
|
'Public Key': onionrcrypto.pub_key.replace('=', ''),
|
||||||
|
'Human-readable Public Key': mnemonickeys.get_human_readable_ID()
|
||||||
}
|
}
|
||||||
|
|
||||||
for detail in details:
|
for detail in details:
|
||||||
|
@ -5,6 +5,7 @@ Sets CLI arguments for Onionr
|
|||||||
from typing import Callable
|
from typing import Callable
|
||||||
|
|
||||||
from .. import onionrstatistics, version, daemonlaunch
|
from .. import onionrstatistics, version, daemonlaunch
|
||||||
|
from .. import pubkeymanager # commands to add or change id
|
||||||
from .. import resetplugins # command to reinstall default plugins
|
from .. import resetplugins # command to reinstall default plugins
|
||||||
|
|
||||||
|
|
||||||
|
27
src/onionrcrypto/__init__.py
Executable file
27
src/onionrcrypto/__init__.py
Executable file
@ -0,0 +1,27 @@
|
|||||||
|
'''
|
||||||
|
Onionr - Private P2P Communication
|
||||||
|
|
||||||
|
This file handles Onionr's cryptography.
|
||||||
|
'''
|
||||||
|
'''
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
'''
|
||||||
|
|
||||||
|
from . import generate, getourkeypair, signing, encryption, cryptoutils
|
||||||
|
generate_deterministic = generate.generate_deterministic
|
||||||
|
generate = generate.generate_pub_key
|
||||||
|
|
||||||
|
keypair = getourkeypair.get_keypair()
|
||||||
|
pub_key = keypair[0]
|
||||||
|
priv_key = keypair[1]
|
5
src/onionrcrypto/cryptoutils/__init__.py
Normal file
5
src/onionrcrypto/cryptoutils/__init__.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
from . import safecompare
|
||||||
|
from . import getpubfrompriv
|
||||||
|
|
||||||
|
safe_compare = safecompare.safe_compare
|
||||||
|
get_pub_key_from_priv = getpubfrompriv.get_pub_key_from_priv
|
28
src/onionrcrypto/cryptoutils/getpubfrompriv.py
Normal file
28
src/onionrcrypto/cryptoutils/getpubfrompriv.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
"""Onionr - Private P2P Communication.
|
||||||
|
|
||||||
|
generate a public ed25519 key from a private one
|
||||||
|
"""
|
||||||
|
from nacl import signing, encoding
|
||||||
|
|
||||||
|
from onionrtypes import UserID, UserIDSecretKey
|
||||||
|
"""
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def get_pub_key_from_priv(priv_key: UserIDSecretKey,
|
||||||
|
raw_encoding: bool = False) -> UserID:
|
||||||
|
return signing.SigningKey(
|
||||||
|
priv_key, encoder=encoding.Base32Encoder).verify_key.encode(
|
||||||
|
encoding.Base32Encoder)
|
15
src/onionrcrypto/cryptoutils/safecompare.py
Normal file
15
src/onionrcrypto/cryptoutils/safecompare.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import hmac
|
||||||
|
|
||||||
|
|
||||||
|
def safe_compare(one, two):
|
||||||
|
# Do encode here to avoid spawning core
|
||||||
|
try:
|
||||||
|
one = one.encode()
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
two = two.encode()
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
return hmac.compare_digest(one, two)
|
||||||
|
|
47
src/onionrcrypto/encryption/__init__.py
Normal file
47
src/onionrcrypto/encryption/__init__.py
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import nacl.encoding, nacl.public, nacl.signing
|
||||||
|
from .. import getourkeypair
|
||||||
|
import unpaddedbase32
|
||||||
|
from onionrutils import bytesconverter, stringvalidators
|
||||||
|
pair = getourkeypair.get_keypair()
|
||||||
|
our_pub_key = unpaddedbase32.repad(pair[0].encode())
|
||||||
|
our_priv_key = unpaddedbase32.repad(pair[1].encode())
|
||||||
|
|
||||||
|
def pub_key_encrypt(data, pubkey, encodedData=False):
|
||||||
|
'''Encrypt to a public key (Curve25519, taken from base32 Ed25519 pubkey)'''
|
||||||
|
pubkey = unpaddedbase32.repad(bytesconverter.str_to_bytes(pubkey))
|
||||||
|
retVal = ''
|
||||||
|
box = None
|
||||||
|
data = bytesconverter.str_to_bytes(data)
|
||||||
|
|
||||||
|
pubkey = nacl.signing.VerifyKey(pubkey, encoder=nacl.encoding.Base32Encoder()).to_curve25519_public_key()
|
||||||
|
|
||||||
|
if encodedData:
|
||||||
|
encoding = nacl.encoding.Base64Encoder
|
||||||
|
else:
|
||||||
|
encoding = nacl.encoding.RawEncoder
|
||||||
|
|
||||||
|
box = nacl.public.SealedBox(pubkey)
|
||||||
|
retVal = box.encrypt(data, encoder=encoding)
|
||||||
|
|
||||||
|
return retVal
|
||||||
|
|
||||||
|
def pub_key_decrypt(data, pubkey='', privkey='', encodedData=False):
|
||||||
|
'''pubkey decrypt (Curve25519, taken from Ed25519 pubkey)'''
|
||||||
|
if pubkey != '':
|
||||||
|
pubkey = unpaddedbase32.repad(bytesconverter.str_to_bytes(pubkey))
|
||||||
|
decrypted = False
|
||||||
|
if encodedData:
|
||||||
|
encoding = nacl.encoding.Base64Encoder
|
||||||
|
else:
|
||||||
|
encoding = nacl.encoding.RawEncoder
|
||||||
|
if privkey == '':
|
||||||
|
privkey = our_priv_key
|
||||||
|
ownKey = nacl.signing.SigningKey(seed=privkey, encoder=nacl.encoding.Base32Encoder()).to_curve25519_private_key()
|
||||||
|
|
||||||
|
if stringvalidators.validate_pub_key(privkey):
|
||||||
|
privkey = nacl.signing.SigningKey(seed=privkey, encoder=nacl.encoding.Base32Encoder()).to_curve25519_private_key()
|
||||||
|
anonBox = nacl.public.SealedBox(privkey)
|
||||||
|
else:
|
||||||
|
anonBox = nacl.public.SealedBox(ownKey)
|
||||||
|
decrypted = anonBox.decrypt(data, encoder=encoding)
|
||||||
|
return decrypted
|
63
src/onionrcrypto/generate.py
Normal file
63
src/onionrcrypto/generate.py
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
"""Onionr - Private P2P Communication.
|
||||||
|
|
||||||
|
functions to generate ed25519 key pairs
|
||||||
|
"""
|
||||||
|
import nacl.signing
|
||||||
|
import nacl.encoding
|
||||||
|
import nacl.pwhash
|
||||||
|
|
||||||
|
import onionrexceptions
|
||||||
|
from onionrutils import bytesconverter
|
||||||
|
import onionrvalues
|
||||||
|
"""
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def generate_pub_key():
|
||||||
|
"""Generate a Ed25519 public key pair.
|
||||||
|
|
||||||
|
return tuple of base32encoded pubkey, privkey
|
||||||
|
"""
|
||||||
|
private_key = nacl.signing.SigningKey.generate()
|
||||||
|
public_key = private_key.verify_key
|
||||||
|
return (public_key, private_key)
|
||||||
|
|
||||||
|
|
||||||
|
def generate_deterministic(passphrase, bypassCheck=False):
|
||||||
|
"""Generate a Ed25519 public key pair from a phase.
|
||||||
|
|
||||||
|
not intended for human-generated key
|
||||||
|
"""
|
||||||
|
passStrength = onionrvalues.PASSWORD_LENGTH
|
||||||
|
# Convert to bytes if not already
|
||||||
|
passphrase = bytesconverter.str_to_bytes(passphrase)
|
||||||
|
# Validate passphrase length
|
||||||
|
if not bypassCheck:
|
||||||
|
if len(passphrase) < passStrength:
|
||||||
|
raise onionrexceptions.PasswordStrengthError(
|
||||||
|
"Passphase must be at least %s characters" % (passStrength,))
|
||||||
|
# KDF values
|
||||||
|
kdf = nacl.pwhash.argon2id.kdf
|
||||||
|
# Does not need to be secret, but must be 16 bytes
|
||||||
|
salt = b"U81Q7llrQcdTP0Ux"
|
||||||
|
ops = nacl.pwhash.argon2id.OPSLIMIT_SENSITIVE
|
||||||
|
mem = nacl.pwhash.argon2id.MEMLIMIT_SENSITIVE
|
||||||
|
|
||||||
|
# Generate seed for ed25519 key
|
||||||
|
key = kdf(32, passphrase, salt, opslimit=ops, memlimit=mem)
|
||||||
|
key = nacl.signing.SigningKey(key)
|
||||||
|
return (
|
||||||
|
key.verify_key.encode(nacl.encoding.Base32Encoder).decode(),
|
||||||
|
key.encode(nacl.encoding.Base32Encoder).decode())
|
36
src/onionrcrypto/getourkeypair.py
Normal file
36
src/onionrcrypto/getourkeypair.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
"""
|
||||||
|
Onionr - Private P2P Communication
|
||||||
|
|
||||||
|
returns our current active keypair
|
||||||
|
"""
|
||||||
|
"""
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import keymanager, config, filepaths
|
||||||
|
from . import generate
|
||||||
|
def get_keypair():
|
||||||
|
key_m = keymanager.KeyManager()
|
||||||
|
if os.path.exists(filepaths.keys_file):
|
||||||
|
if len(config.get('general.public_key', '')) > 0:
|
||||||
|
pubKey = config.get('general.public_key')
|
||||||
|
else:
|
||||||
|
pubKey = key_m.getPubkeyList()[0]
|
||||||
|
privKey = key_m.getPrivkey(pubKey)
|
||||||
|
else:
|
||||||
|
keys = generate.generate_pub_key()
|
||||||
|
pubKey = keys[0]
|
||||||
|
privKey = keys[1]
|
||||||
|
key_m.addKey(pubKey, privKey)
|
||||||
|
return (pubKey, privKey)
|
45
src/onionrcrypto/signing/__init__.py
Normal file
45
src/onionrcrypto/signing/__init__.py
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import base64, binascii
|
||||||
|
|
||||||
|
import unpaddedbase32
|
||||||
|
import nacl.encoding, nacl.signing, nacl.exceptions
|
||||||
|
|
||||||
|
from onionrutils import bytesconverter
|
||||||
|
from onionrutils import mnemonickeys
|
||||||
|
import logger
|
||||||
|
|
||||||
|
def ed_sign(data, key, encodeResult=False):
|
||||||
|
'''Ed25519 sign data'''
|
||||||
|
key = unpaddedbase32.repad(bytesconverter.str_to_bytes(key))
|
||||||
|
try:
|
||||||
|
data = data.encode()
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
key = nacl.signing.SigningKey(seed=key, encoder=nacl.encoding.Base32Encoder)
|
||||||
|
retData = ''
|
||||||
|
if encodeResult:
|
||||||
|
retData = key.sign(data, encoder=nacl.encoding.Base64Encoder).signature.decode() # .encode() is not the same as nacl.encoding
|
||||||
|
else:
|
||||||
|
retData = key.sign(data).signature
|
||||||
|
return retData
|
||||||
|
|
||||||
|
def ed_verify(data, key, sig, encodedData=True):
|
||||||
|
'''Verify signed data (combined in nacl) to an ed25519 key'''
|
||||||
|
key = unpaddedbase32.repad(bytesconverter.str_to_bytes(key))
|
||||||
|
try:
|
||||||
|
key = nacl.signing.VerifyKey(key=key, encoder=nacl.encoding.Base32Encoder)
|
||||||
|
except nacl.exceptions.ValueError:
|
||||||
|
return False
|
||||||
|
except binascii.Error:
|
||||||
|
logger.warn('Could not load key for verification, invalid padding')
|
||||||
|
return False
|
||||||
|
retData = False
|
||||||
|
sig = base64.b64decode(sig)
|
||||||
|
try:
|
||||||
|
data = data.encode()
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
retData = key.verify(data, sig) # .encode() is not the same as nacl.encoding
|
||||||
|
except nacl.exceptions.BadSignatureError:
|
||||||
|
pass
|
||||||
|
return retData
|
120
src/onionrsetup/dbcreator.py
Executable file
120
src/onionrsetup/dbcreator.py
Executable file
@ -0,0 +1,120 @@
|
|||||||
|
"""Onionr - Private P2P Communication.
|
||||||
|
|
||||||
|
DBCreator, creates sqlite3 databases used by Onionr
|
||||||
|
"""
|
||||||
|
"""
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
"""
|
||||||
|
import sqlite3, os
|
||||||
|
from coredb import dbfiles
|
||||||
|
import filepaths
|
||||||
|
|
||||||
|
def createAddressDB():
|
||||||
|
'''
|
||||||
|
Generate the address database
|
||||||
|
|
||||||
|
types:
|
||||||
|
1: I2P b32 address
|
||||||
|
2: Tor v2 (like facebookcorewwwi.onion)
|
||||||
|
3: Tor v3
|
||||||
|
'''
|
||||||
|
if os.path.exists(dbfiles.address_info_db):
|
||||||
|
raise FileExistsError("Address database already exists")
|
||||||
|
conn = sqlite3.connect(dbfiles.address_info_db)
|
||||||
|
c = conn.cursor()
|
||||||
|
c.execute('''CREATE TABLE adders(
|
||||||
|
address text,
|
||||||
|
type int,
|
||||||
|
knownPeer text,
|
||||||
|
speed int,
|
||||||
|
success int,
|
||||||
|
powValue text,
|
||||||
|
failure int,
|
||||||
|
lastConnect int,
|
||||||
|
lastConnectAttempt int,
|
||||||
|
trust int,
|
||||||
|
introduced int
|
||||||
|
);
|
||||||
|
''')
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
def createPeerDB():
|
||||||
|
'''
|
||||||
|
Generate the peer sqlite3 database and populate it with the peers table.
|
||||||
|
'''
|
||||||
|
if os.path.exists(dbfiles.user_id_info_db):
|
||||||
|
raise FileExistsError("User database already exists")
|
||||||
|
# generate the peer database
|
||||||
|
conn = sqlite3.connect(dbfiles.user_id_info_db)
|
||||||
|
c = conn.cursor()
|
||||||
|
c.execute('''CREATE TABLE peers(
|
||||||
|
ID text not null,
|
||||||
|
name text,
|
||||||
|
adders text,
|
||||||
|
dateSeen not null,
|
||||||
|
trust int,
|
||||||
|
hashID text);
|
||||||
|
''')
|
||||||
|
c.execute('''CREATE TABLE forwardKeys(
|
||||||
|
peerKey text not null,
|
||||||
|
forwardKey text not null,
|
||||||
|
date int not null,
|
||||||
|
expire int not null
|
||||||
|
);''')
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def createForwardKeyDB():
|
||||||
|
'''
|
||||||
|
Create the forward secrecy key db (*for *OUR* keys*)
|
||||||
|
'''
|
||||||
|
if os.path.exists(dbfiles.forward_keys_db):
|
||||||
|
raise FileExistsError("Block database already exists")
|
||||||
|
conn = sqlite3.connect(dbfiles.forward_keys_db)
|
||||||
|
c = conn.cursor()
|
||||||
|
c.execute('''CREATE TABLE myForwardKeys(
|
||||||
|
peer text not null,
|
||||||
|
publickey text not null,
|
||||||
|
privatekey text not null,
|
||||||
|
date int not null,
|
||||||
|
expire int not null
|
||||||
|
);
|
||||||
|
''')
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def create_blacklist_db():
|
||||||
|
if os.path.exists(dbfiles.blacklist_db):
|
||||||
|
raise FileExistsError("Blacklist db already exists")
|
||||||
|
conn = sqlite3.connect(dbfiles.blacklist_db, timeout=10)
|
||||||
|
c = conn.cursor()
|
||||||
|
# Create table
|
||||||
|
c.execute('''CREATE TABLE blacklist(
|
||||||
|
hash text primary key not null,
|
||||||
|
dataType int,
|
||||||
|
blacklistDate int,
|
||||||
|
expire int
|
||||||
|
);
|
||||||
|
''')
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
|
||||||
|
create_funcs = [createAddressDB, createPeerDB,
|
||||||
|
createForwardKeyDB, create_blacklist_db]
|
@ -33,6 +33,8 @@ def delete_run_files():
|
|||||||
|
|
||||||
Test: test_cleanup.py
|
Test: test_cleanup.py
|
||||||
"""
|
"""
|
||||||
|
_safe_remove(filepaths.public_API_host_file)
|
||||||
|
_safe_remove(filepaths.private_API_host_file)
|
||||||
_safe_remove(filepaths.daemon_mark_file)
|
_safe_remove(filepaths.daemon_mark_file)
|
||||||
_safe_remove(filepaths.lock_file)
|
_safe_remove(filepaths.lock_file)
|
||||||
_safe_remove(filepaths.gossip_server_socket_file)
|
_safe_remove(filepaths.gossip_server_socket_file)
|
||||||
|
50
src/onionrutils/mnemonickeys.py
Normal file
50
src/onionrutils/mnemonickeys.py
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
"""
|
||||||
|
Onionr - Private P2P Communication
|
||||||
|
|
||||||
|
convert a base32 string (intended for ed25519 user ids) to pgp word list
|
||||||
|
"""
|
||||||
|
import base64
|
||||||
|
|
||||||
|
import niceware
|
||||||
|
import unpaddedbase32
|
||||||
|
|
||||||
|
import onionrcrypto
|
||||||
|
import onionrvalues
|
||||||
|
"""
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
DELIMITER = '-'
|
||||||
|
|
||||||
|
def get_human_readable_ID(pub=''):
|
||||||
|
"""gets a human readable ID from a public key"""
|
||||||
|
if pub == '':
|
||||||
|
pub = onionrcrypto.pub_key
|
||||||
|
|
||||||
|
if not len(pub) == onionrvalues.MAIN_PUBLIC_KEY_SIZE:
|
||||||
|
pub = base64.b32decode(pub)
|
||||||
|
|
||||||
|
return DELIMITER.join(niceware.bytes_to_passphrase(pub))
|
||||||
|
#return niceware.bytes_to_passphrase(pub).replace(' ', DELIMITER)
|
||||||
|
|
||||||
|
def get_base32(words):
|
||||||
|
"""converts mnemonic to base32"""
|
||||||
|
if DELIMITER not in words and not type(words) in (type(list), type(tuple)): return words
|
||||||
|
|
||||||
|
try:
|
||||||
|
return unpaddedbase32.b32encode(niceware.passphrase_to_bytes(words.split(DELIMITER)))
|
||||||
|
except AttributeError:
|
||||||
|
ret = unpaddedbase32.b32encode(niceware.passphrase_to_bytes(words))
|
||||||
|
return ret
|
@ -44,3 +44,11 @@ def create_dirs():
|
|||||||
" already exists and is not owned by the same user")
|
" already exists and is not owned by the same user")
|
||||||
|
|
||||||
os.chmod(home, stat.S_IRWXU)
|
os.chmod(home, stat.S_IRWXU)
|
||||||
|
|
||||||
|
from onionrsetup import dbcreator
|
||||||
|
|
||||||
|
for db in dbcreator.create_funcs:
|
||||||
|
try:
|
||||||
|
db()
|
||||||
|
except FileExistsError:
|
||||||
|
pass
|
||||||
|
@ -1 +0,0 @@
|
|||||||
PYTHONPATH=./venv/bin/python310:../../src/:./
|
|
@ -1,4 +0,0 @@
|
|||||||
{ "name": "repl",
|
|
||||||
"version": "0.0.0",
|
|
||||||
"author": "onionr"
|
|
||||||
}
|
|
@ -1,57 +0,0 @@
|
|||||||
"""Onionr - Private P2P Communication.
|
|
||||||
|
|
||||||
read-eval-print-loop plugin for Onionr
|
|
||||||
"""
|
|
||||||
|
|
||||||
import locale
|
|
||||||
|
|
||||||
|
|
||||||
locale.setlocale(locale.LC_ALL, '')
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
import readline
|
|
||||||
import rlcompleter
|
|
||||||
readline.parse_and_bind("tab: complete")
|
|
||||||
|
|
||||||
# locals for the repl
|
|
||||||
from gossip.peerset import gossip_peer_set
|
|
||||||
|
|
||||||
from code import InteractiveConsole
|
|
||||||
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)))
|
|
||||||
# import after path insert
|
|
||||||
|
|
||||||
"""
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
plugin_name = 'repl'
|
|
||||||
PLUGIN_VERSION = '0.0.0'
|
|
||||||
|
|
||||||
def on_primary_loop(event_name, data):
|
|
||||||
"""Run a REPL on the primary loop"""
|
|
||||||
header = """You are now in the Onionr REPL. Type 'exit()' to exit.
|
|
||||||
|
|
||||||
Enter repl_locals to see the (default) special locals available to you.
|
|
||||||
"""
|
|
||||||
footer = "Exiting Onionr REPL."
|
|
||||||
repl_locals = {
|
|
||||||
'gossip_peer_set': gossip_peer_set,
|
|
||||||
}
|
|
||||||
|
|
||||||
InteractiveConsole(
|
|
||||||
repl_locals | {"repl_locals": repl_locals}).interact(header, footer)
|
|
||||||
raise KeyboardInterrupt
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user