Switch to client-side decryption; encrypt title; dark theme icons

pull/12/head 0.4.2
Cesura 4 years ago
parent 6389b1b523
commit 25b7510fe3

@ -6,7 +6,7 @@ from os import environ
from distutils.util import strtobool
from threading import Thread
pastey_version = "0.4.1"
pastey_version = "0.4.2"
loaded_config = {}
loaded_themes = []

@ -35,6 +35,7 @@ def get_recent(limit=config.recent_pastes):
# Replace preview if encrypted
if paste['encrypted']:
paste['content'] = "[Encrypted]"
paste['title'] = "[Encrypted]"
recent_pastes.append(paste)
i += 1
@ -67,14 +68,6 @@ def get_paste(unique_id, key=""):
with open(file_path, "w") as fp:
fp.write(json.dumps(paste))
# Decrypt content, if necessary
try:
if key != "":
cipher_suite = Fernet(key.encode('utf-8'))
paste['content'] = cipher_suite.decrypt(paste['content'].encode('utf-8')).decode('utf-8')
except Exception as e:
return 401
return paste
else:
return None
@ -104,7 +97,10 @@ def new_paste(title, content, source_ip, expires=0, single=False, encrypt=False)
if encrypt:
init_key = Fernet.generate_key()
cipher_suite = Fernet(init_key)
# Encrypt title and content
content = cipher_suite.encrypt(content.encode('utf-8')).decode('utf-8')
title = cipher_suite.encrypt(title.encode('utf-8')).decode('utf-8')
key = init_key.decode('utf-8')
# Check if single use is set

@ -72,24 +72,6 @@ def view(unique_id):
else:
abort(404)
# View paste page (encrypted)
@app.route("/view/<unique_id>/<key>")
def view_key(unique_id, key):
content = functions.get_paste(unique_id, key=key)
if content == 401:
abort(401)
elif content is not None:
return render_template("view.html",
paste=content,
url=common.build_url(request, "/view/" + unique_id + "/" + key),
whitelisted=common.verify_whitelist(common.get_source_ip(request)),
active_theme=common.set_theme(request),
themes=loaded_themes)
else:
abort(404)
# Delete paste
@app.route("/delete/<unique_id>")
def delete(unique_id):
@ -143,9 +125,9 @@ def paste():
# Return link if cli form option was set
if 'cli' in request.form:
return common.build_url(request, "/view/" + unique_id + "/" + quote(key)), 200
return common.build_url(request, "/view/" + unique_id + "#" + quote(key)), 200
else:
return redirect("/view/" + unique_id + "/" + quote(key))
return redirect("/view/" + unique_id + "#" + quote(key))
else:
if 'cli' in request.form:
return common.build_url(request, "/view/" + unique_id), 200
@ -199,7 +181,7 @@ def paste_json():
unique_id, key = functions.new_paste(title, content, source_ip, expires=expiration, single=single, encrypt=encrypt)
if encrypt:
return {
"link": common.build_url(request, "/view/" + unique_id + "/" + quote(key))
"link": common.build_url(request, "/view/" + unique_id + "#" + quote(key))
}, 200
else:
return {

@ -45,3 +45,7 @@
.pastey-checkbox {
padding-top:10px;
}
.pastey-title {
word-wrap:break-word;
}

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

@ -14,3 +14,39 @@ function resetTheme() {
document.cookie = "pastey_theme=; Expires=Thu, 01 Jan 1970 00:00:01 GMT; path=/; SameSite=Lax;";
location.reload();
}
function decryptPaste() {
var key = window.location.hash.substring(1);
$("#paste-url").val($("#paste-url").val() + window.location.hash);
try {
var secret = new fernet.Secret(decodeURIComponent(key));
// Decrypt title
var title_token = new fernet.Token({
secret: secret,
token: $("#pastey-title").text(),
ttl: 0
});
var title = title_token.decode();
$("#pastey-title").text(title);
document.title = title + ' | Pastey';
// Decrypt content
var content_token = new fernet.Token({
secret: secret,
token: $("#pastey-content").text(),
ttl: 0
});
$("#pastey-content").text(content_token.decode());
// Show success message
$("#pastey-decrypt-success").css("display", "block");
} catch(error) {
// Show error message
$("#pastey-decrypt-failed").css("display", "block");
}
}

File diff suppressed because it is too large Load Diff

@ -119,7 +119,7 @@
<div class="row">
<div class="col-md-4 mb-4">
<div class="bg-image hover-overlay shadow-1-strong rounded ripple pastey-preview-image" data-mdb-ripple-color="light">
<img src="/static/img/language/{{ paste.icon }}.png" class="img-fluid" />
<img src="/static/img/language/{{ active_theme }}/{{ paste.icon }}.png" class="img-fluid" />
<a href="/view/{{ paste.unique_id }}">
<div class="mask" style="background-color: rgba(251, 251, 251, 0.15);"></div>
</a>

@ -95,7 +95,9 @@
{% else %}
<img src="/static/img/unencrypted.png" width="30px" height="30px" /><br /><br />
{% endif %}
<h1 class="mb-3 h2">{{ paste.title }}</h1>
<div class="pastey-title">
<h1 class="mb-3 h2" id="pastey-title">{{ paste.title }}</h1>
</div>
<span style="font-weight:bold;">Format: </span><span>{{ paste.language }}</span><br />
<span style="font-weight:bold;">Date: </span><span>{{ paste.timestamp }}</span><br />
{% if paste.expiration is defined and paste.expiration != "" %}
@ -123,6 +125,13 @@
</div>
</div>
{% endif %}
<div id="pastey-decrypt-failed" style="display:none;"><br />
<span class="badge rounded-pill bg-danger">Error: could not decrypt paste with the given key</span>
</div>
<div id="pastey-decrypt-success" style="display:none;"><br />
<span class="badge rounded-pill bg-success">&nbsp;<i class="fas fa-lock-open"></i>&nbsp;&nbsp;&nbsp;Paste has been decrypted successfully&nbsp;</span>
</div>
</div>
<!-- Jumbotron -->
</header>
@ -132,7 +141,7 @@
<div class="container">
<div class="row">
<div class="col-md-12 mb-4">
<pre class="prettyprint linenums">{{ paste.content }}</pre>
<pre class="prettyprint linenums" id="pastey-content">{{ paste.content }}</pre>
</div>
</div>
@ -173,21 +182,28 @@
<!--JS-->
<script type="text/javascript" src="/static/js/jquery.min.js"></script>
<script type="text/javascript" src="/static/js/fernet.js"></script>
<script type="text/javascript" src="/static/js/common.js"></script>
<script type="text/javascript" src="/static/js/qrcode.min.js"></script>
<script type="text/javascript" src="/static/js/mdb.min.js"></script>
<script type="text/javascript" src="/static/js/common.js"></script>
<script type="text/javascript" src="/static/js/prettify.min.js"></script>
<script type="text/javascript" src="/static/js/run_prettify.js"></script>
<!-- Generate QR code -->
<!-- Decrypt paste and generate QR code -->
<script type="text/javascript">
var qrcode = new QRCode("qrcode", {
text: "{{ url }}",
width: 256,
height: 256,
colorDark : "#000000",
colorLight : "#ffffff",
correctLevel : QRCode.CorrectLevel.H
$(document).ready(function() {
if (window.location.hash.length > 0) {
decryptPaste();
}
var qrcode = new QRCode("qrcode", {
text: $("#paste-url").val(),
width: 256,
height: 256,
colorDark : "#000000",
colorLight : "#ffffff",
correctLevel : QRCode.CorrectLevel.H
});
});
</script>
</body>

Loading…
Cancel
Save