Felix Brendel před 5 roky
revize
402cbb94a6
5 změnil soubory, kde provedl 353 přidání a 0 odebrání
  1. +122
    -0
      decipher.js
  2. +4
    -0
      input_form.html
  3. +131
    -0
      passwordify_html.py
  4. +9
    -0
      test/test.html
  5. +87
    -0
      test/test.html.pw.html

+ 122
- 0
decipher.js Zobrazit soubor

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

+ 4
- 0
input_form.html Zobrazit soubor

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

+ 131
- 0
passwordify_html.py Zobrazit soubor

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

+ 9
- 0
test/test.html Zobrazit soubor

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

+ 87
- 0
test/test.html.pw.html Zobrazit soubor

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

Načítá se…
Zrušit
Uložit