* 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
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user