yes
This commit is contained in:
+122
@@ -0,0 +1,122 @@
|
|||||||
|
// function clone_script_node(node){
|
||||||
|
// // console.log("\n\n\nnew script!")
|
||||||
|
// var script = document.createElement("script");
|
||||||
|
// script.text = node.innerHTML;
|
||||||
|
// // console.log("text: " + script.text)
|
||||||
|
// var i = -1, attrs = node.attributes, attr;
|
||||||
|
// while (++i < attrs.length) {
|
||||||
|
// script.setAttribute((attr = attrs[i]).name, attr.value);
|
||||||
|
// if (attr.name === "src")
|
||||||
|
// console.log(attr.value)
|
||||||
|
// }
|
||||||
|
// return script;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// function replace_all_script_nodes(node) {
|
||||||
|
// if (node.tagName === 'SCRIPT') {
|
||||||
|
// node.parentNode.replaceChild(clone_script_node(node), node);
|
||||||
|
// } else {
|
||||||
|
// var i = -1, children = node.childNodes;
|
||||||
|
// while (++i < children.length) {
|
||||||
|
// replace_all_script_nodes(children[i]);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return node;
|
||||||
|
// }
|
||||||
|
|
||||||
|
function insertHTML(html){
|
||||||
|
// if no append is requested, clear the target element
|
||||||
|
// if(!append) dest.innerHTML = '';
|
||||||
|
// create a temporary container and insert provided HTML code
|
||||||
|
let container = document.createElement('div');
|
||||||
|
container.innerHTML = html;
|
||||||
|
// cache a reference to all the scripts in the container
|
||||||
|
let scripts = container.querySelectorAll('script');
|
||||||
|
// get all child elements and clone them in the target element
|
||||||
|
let nodes = container.childNodes;
|
||||||
|
// for( let i=0; i< nodes.length; i++) dest.appendChild( nodes[i].cloneNode(true) );
|
||||||
|
// force the found scripts to execute...
|
||||||
|
for( let i=0; i< scripts.length; i++){
|
||||||
|
let script = document.createElement('script');
|
||||||
|
script.type = scripts[i].type || 'text/javascript';
|
||||||
|
if( scripts[i].hasAttribute('src') ) script.src = scripts[i].src;
|
||||||
|
script.innerHTML = scripts[i].innerHTML;
|
||||||
|
document.head.appendChild(script);
|
||||||
|
document.head.removeChild(script);
|
||||||
|
}
|
||||||
|
// done!
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function decrypt_page() {
|
||||||
|
var key_str = ""
|
||||||
|
var html_name = window.location.pathname;
|
||||||
|
var allcookies = document.cookie;
|
||||||
|
cookiearray = allcookies.split(';');
|
||||||
|
for(var i=0; i<cookiearray.length; i++) {
|
||||||
|
name = cookiearray[i].split('=')[0].trim();
|
||||||
|
value = cookiearray[i].split('=')[1];
|
||||||
|
if (name == html_name)
|
||||||
|
key_str = value;
|
||||||
|
if (name == "__master__") {
|
||||||
|
key_str = value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key_str.length == 0)
|
||||||
|
key_str = document.querySelector('input[name=pwd]').value
|
||||||
|
|
||||||
|
// check key length
|
||||||
|
if (key_str.length != 16 &&
|
||||||
|
key_str.length != 24 &&
|
||||||
|
key_str.length != 32)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var entered_key = aesjs.utils.utf8.toBytes(key_str);
|
||||||
|
var enc_bytes = aesjs.utils.hex.toBytes(enc_hex_body)
|
||||||
|
|
||||||
|
// check if the user input / loaded cookie is the master key
|
||||||
|
var aesCtr = new aesjs.ModeOfOperation.ctr(entered_key, new aesjs.Counter(initial_counter))
|
||||||
|
var master_key_dec_real_key = aesCtr.decrypt(aesjs.utils.hex.toBytes(master_key_enc_real_key))
|
||||||
|
|
||||||
|
aesCtr = new aesjs.ModeOfOperation.ctr(master_key_dec_real_key, new aesjs.Counter(initial_counter))
|
||||||
|
var dec_bytes = aesCtr.decrypt(enc_bytes)
|
||||||
|
|
||||||
|
// Convert our bytes back into text
|
||||||
|
var dec_text = aesjs.utils.utf8.fromBytes(dec_bytes)
|
||||||
|
if (!dec_text.endsWith(correct_key_marker)) {
|
||||||
|
// check if it is a regular password
|
||||||
|
aesCtr = new aesjs.ModeOfOperation.ctr(entered_key, new aesjs.Counter(initial_counter))
|
||||||
|
var org_key_dec_real_key = aesCtr.decrypt(aesjs.utils.hex.toBytes(org_key_enc_real_key))
|
||||||
|
|
||||||
|
aesCtr = new aesjs.ModeOfOperation.ctr(org_key_dec_real_key, new aesjs.Counter(initial_counter))
|
||||||
|
dec_bytes = aesCtr.decrypt(enc_bytes)
|
||||||
|
dec_text = aesjs.utils.utf8.fromBytes(dec_bytes)
|
||||||
|
|
||||||
|
if (!dec_text.endsWith(correct_key_marker)) {
|
||||||
|
key_str = "";
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
// entered correct file key
|
||||||
|
document.cookie = html_name + "=" + key_str;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// entered correct master key
|
||||||
|
document.cookie = "__master__=" + key_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert our bytes back into text
|
||||||
|
// var dec_text = aesjs.utils.utf8.fromBytes(dec_bytes)
|
||||||
|
var dec_text = new TextDecoder().decode(dec_bytes)
|
||||||
|
document.body.outerHTML = "<body" + dec_text + "</body>"
|
||||||
|
|
||||||
|
// insertHTML(document.body.innerHTML)
|
||||||
|
// replace_all_script_nodes(document.getElementsByTagName("body")[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.onload = decrypt_page
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<div style="line-height: initial; position: absolute; left: 50%; top: 50%; -webkit-transform: translate(-50%, -50%); transform: translate(-50%, -50%);">
|
||||||
|
<p id="sd" onclick="decrypt_page()" style="margin: 0 auto;font-size:100px;text-align:center">🔒</p>
|
||||||
|
<input type="password" id="pwd" name="pwd">
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,131 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import argparse
|
||||||
|
import pyaes
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import random
|
||||||
|
import string
|
||||||
|
|
||||||
|
sample_usage = """example:
|
||||||
|
python passwordify_html.py file.html --password "this is the password"
|
||||||
|
python passwordify_html.py file.html --password "this is the password" --master-password "master-password"
|
||||||
|
"""
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description="Generate a chart showing character traits.",
|
||||||
|
epilog=sample_usage,
|
||||||
|
formatter_class=argparse.RawDescriptionHelpFormatter)
|
||||||
|
|
||||||
|
parser.add_argument('input_file', type=str, metavar="input",
|
||||||
|
help='the html file')
|
||||||
|
parser.add_argument("--password", "-p", dest="password",
|
||||||
|
required=False, type=str, metavar="page password",
|
||||||
|
help="The names of the character traits")
|
||||||
|
parser.add_argument("--master-password", "-m", dest="master_password",
|
||||||
|
required=False, type=str, metavar="master password",
|
||||||
|
help="The values for the character traits")
|
||||||
|
parser.add_argument("--output", "-o", dest="output_file",
|
||||||
|
required=False, type=str, metavar="output",
|
||||||
|
help="The file which should be created")
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
script_dir = os.path.dirname(__file__)
|
||||||
|
|
||||||
|
# passwords length must be in [16, 24, 32]
|
||||||
|
# at least one must be supplied, the other is chosen random
|
||||||
|
if args.password:
|
||||||
|
assert(len(args.password) in [16, 24, 32])
|
||||||
|
if not args.master_password:
|
||||||
|
args.master_password = "".join(random.choice(string.ascii_letters) for i in range(32))
|
||||||
|
elif args.master_password:
|
||||||
|
assert(len(args.master_password) in [16, 24, 32])
|
||||||
|
if not args.password:
|
||||||
|
args.password = "".join(random.choice(string.ascii_letters) for i in range(32))
|
||||||
|
else:
|
||||||
|
assert(not "At least one of password or master password must be supplied")
|
||||||
|
|
||||||
|
|
||||||
|
# if no out_file was passed, append .pw.html to in_file
|
||||||
|
in_file = args.input_file
|
||||||
|
out_file = args.output_file
|
||||||
|
if not out_file:
|
||||||
|
out_file = f"{in_file}.pw.html"
|
||||||
|
|
||||||
|
print(f"passwordifying {in_file} -> {out_file}")
|
||||||
|
|
||||||
|
# read the whole html file
|
||||||
|
with open(in_file, "r") as in_file_handle:
|
||||||
|
text = in_file_handle.read()
|
||||||
|
|
||||||
|
# if the html has no body tag, then just copy it over
|
||||||
|
if "<body" not in text:
|
||||||
|
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
initial_counter = random.choice(list(range(128)))
|
||||||
|
|
||||||
|
# generate a real key
|
||||||
|
real_key = "".join(random.choice(string.ascii_letters) for i in range(32)).encode("utf-8")
|
||||||
|
|
||||||
|
aes = pyaes.AESModeOfOperationCTR(args.password.encode("utf-8"),
|
||||||
|
counter=pyaes.Counter(initial_value=initial_counter))
|
||||||
|
org_key_enc_real_key = aes.encrypt(real_key).hex()
|
||||||
|
|
||||||
|
aes = pyaes.AESModeOfOperationCTR(args.master_password.encode("utf-8"),
|
||||||
|
counter=pyaes.Counter(initial_value=initial_counter))
|
||||||
|
master_key_enc_real_key = aes.encrypt(real_key).hex()
|
||||||
|
|
||||||
|
|
||||||
|
#extract header, body, and footer
|
||||||
|
text_list = text.split("<body")
|
||||||
|
# assert that the <body> tag only appears once
|
||||||
|
if len(text_list) != 2:
|
||||||
|
print(f"len(text_list) is {len(text_list)}")
|
||||||
|
assert(False)
|
||||||
|
|
||||||
|
header = text_list[0]
|
||||||
|
text_list = text_list[1].split("</body>")
|
||||||
|
# assert that the </body> tag only appears once
|
||||||
|
assert(len(text_list) == 2)
|
||||||
|
body, footer = text_list
|
||||||
|
|
||||||
|
# read in the decipher function text
|
||||||
|
with open(os.path.join(script_dir, "decipher.js"), "r") as decipher_file:
|
||||||
|
decipher_function_text = decipher_file.read()
|
||||||
|
|
||||||
|
# read in the html input prompt
|
||||||
|
with open(os.path.join(script_dir, "input_form.html"), "r") as html_prompt_file:
|
||||||
|
html_prompt_text = html_prompt_file.read()
|
||||||
|
|
||||||
|
|
||||||
|
# have a "correct_marker" so the decrypter can check if the password was correct
|
||||||
|
# by identifiying if the decryped text ends with the correct_marker
|
||||||
|
correct_key_marker = "<!--Correct Key-->"
|
||||||
|
body = body + correct_key_marker
|
||||||
|
aes = pyaes.AESModeOfOperationCTR(real_key,
|
||||||
|
counter=pyaes.Counter(initial_value=initial_counter))
|
||||||
|
|
||||||
|
real_key_enc_body = aes.encrypt(body.encode("utf-8")).hex()
|
||||||
|
header = header.replace("</head>", f"""
|
||||||
|
<script type="text/javascript" src="https://cdn.rawgit.com/ricmoo/aes-js/e27b99df/index.js"></script>
|
||||||
|
<script>
|
||||||
|
var master_key_enc_real_key = "{master_key_enc_real_key}";
|
||||||
|
var org_key_enc_real_key = "{org_key_enc_real_key}";
|
||||||
|
var correct_key_marker = "{correct_key_marker}"
|
||||||
|
var initial_counter = {initial_counter};
|
||||||
|
var enc_hex_body = "{real_key_enc_body}";
|
||||||
|
</script>
|
||||||
|
<script>
|
||||||
|
{decipher_function_text}
|
||||||
|
</script>
|
||||||
|
</head>""")
|
||||||
|
text = " ".join([header, f"""
|
||||||
|
<body>
|
||||||
|
{html_prompt_text}
|
||||||
|
</body>""", footer])
|
||||||
|
|
||||||
|
# write html to new location
|
||||||
|
with open(out_file, "wb") as new_html:
|
||||||
|
new_html.write(text.encode('utf-8'))
|
||||||
|
|
||||||
|
print(f"successfully passwordified {in_file}")
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Example</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>This is an example of a simple HTML page with one paragraph.</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Example</title>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="https://cdn.rawgit.com/ricmoo/aes-js/e27b99df/index.js"></script>
|
||||||
|
<script>
|
||||||
|
var master_key_enc_real_key = "04a2d6b170354946e39f6d53e8d8d341400c9fce9eb8a766398be99ecfc3bfff";
|
||||||
|
var org_key_enc_real_key = "15d34714d9853ae918ec53a7fabae45cc9536c210f77ecb0822c275fe6c11b49";
|
||||||
|
var correct_key_marker = "<!--Correct Key-->"
|
||||||
|
var initial_counter = 5;
|
||||||
|
var enc_hex_body = "d3e739429a8408b664023e88700b076cf058d57f6e10cd910c0b7fa4e01ba594b2e2d1a8c226b24022fe3f9ea15942fae2acd6fb70438677cf3925d522780f842a1f05512b3080589ee7148b7905327398df6c1bf8611fe11dd3fc857c0ca10dc5d1e4";
|
||||||
|
</script>
|
||||||
|
<script>
|
||||||
|
function decrypt_page() {
|
||||||
|
var key_str = document.querySelector('input[name=pwd]').value
|
||||||
|
var html_name = window.location.pathname;
|
||||||
|
var allcookies = document.cookie;
|
||||||
|
cookiearray = allcookies.split(';');
|
||||||
|
for(var i=0; i<cookiearray.length; i++) {
|
||||||
|
name = cookiearray[i].split('=')[0].trim();
|
||||||
|
value = cookiearray[i].split('=')[1];
|
||||||
|
if (name == html_name)
|
||||||
|
key_str = value;
|
||||||
|
if (name == "__master__") {
|
||||||
|
key_str = value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check key length
|
||||||
|
if (key_str.length != 16 &&
|
||||||
|
key_str.length != 24 &&
|
||||||
|
key_str.length != 32)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var entered_key = aesjs.utils.utf8.toBytes(key_str);
|
||||||
|
var enc_bytes = aesjs.utils.hex.toBytes(enc_hex_body)
|
||||||
|
|
||||||
|
// check if the user input / loaded cookie is the master key
|
||||||
|
var aesCtr = new aesjs.ModeOfOperation.ctr(entered_key, new aesjs.Counter(initial_counter))
|
||||||
|
var master_key_dec_real_key = aesCtr.decrypt(aesjs.utils.hex.toBytes(master_key_enc_real_key))
|
||||||
|
|
||||||
|
aesCtr = new aesjs.ModeOfOperation.ctr(master_key_dec_real_key, new aesjs.Counter(initial_counter))
|
||||||
|
var dec_bytes = aesCtr.decrypt(enc_bytes)
|
||||||
|
|
||||||
|
// Convert our bytes back into text
|
||||||
|
var dec_text = aesjs.utils.utf8.fromBytes(dec_bytes)
|
||||||
|
if (!dec_text.startsWith(correct_key_marker)) {
|
||||||
|
// check if it is a regular password
|
||||||
|
aesCtr = new aesjs.ModeOfOperation.ctr(entered_key, new aesjs.Counter(initial_counter))
|
||||||
|
var org_key_dec_real_key = aesCtr.decrypt(aesjs.utils.hex.toBytes(org_key_enc_real_key))
|
||||||
|
|
||||||
|
aesCtr = new aesjs.ModeOfOperation.ctr(org_key_dec_real_key, new aesjs.Counter(initial_counter))
|
||||||
|
dec_bytes = aesCtr.decrypt(enc_bytes)
|
||||||
|
dec_text = aesjs.utils.utf8.fromBytes(dec_bytes)
|
||||||
|
|
||||||
|
if (!dec_text.startsWith(correct_key_marker)) {
|
||||||
|
key_str = "";
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
// entered correct file key
|
||||||
|
document.cookie = html_name + "=" + key_str;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// entered correct master key
|
||||||
|
document.cookie = "__master__=" + key_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert our bytes back into text
|
||||||
|
// var dec_text = aesjs.utils.utf8.fromBytes(dec_bytes)
|
||||||
|
var dec_text = new TextDecoder().decode(dec_bytes)
|
||||||
|
document.body.innerHTML = dec_text
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div style="position: absolute; left: 50%; top: 50%; -webkit-transform: translate(-50%, -50%); transform: translate(-50%, -50%);">
|
||||||
|
<p id="sd" onclick="decrypt_page()" style="margin: 0 auto;font-size:100px;text-align:center">🔒</p>
|
||||||
|
<input type="password" id="pwd" name="pwd">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user