<?php 
    
/**************************************************************************
        LICENCE
        
        - You may copy and redistribute this file under the conditions:
            1. The file is credited to lucb1e
            2. The file remains unmodified, including this licence
        
        - You may modify and redistribute this file under these conditions:
          (This includes porting to another language.)
            1. It mentions that "part of the code was written by lucb1e".
            2. The name of the project is changed.
            3. The licence remains unmodified.
            4. The source code must be available in an automated way, for
               example as a file download. Contacting you to obtain the source
               is not considered automated.
            5. How to obtain the source must be clearly stated when a user
               obtains the application or modification you've made.
        
        - You may use the file however you like it, commercially or not.
        
        - Since you perform the actions, you will at all times be responsible
          for any results. This includes damages, physically or emotionally or
          however you like them. You can't blame me for anything you did with
          this file or any information/data you obtained from it.
        
        - As by Dutch law, I remain the copyright holder of this file,
          and I can at all times decide what to do with the licence. Any copies
          made before a licence change, will remain under the old licence.
        
        - Fork me on pastebin. :)
        
        - Copyright 2012, lucb1e, The Netherlands.
        
    **************************************************************************/
    
    
if (isset($_GET["source"])) {
        if (isset(
$_GET["raw"])) {
            
header("Content-type: text/plain");
            
readfile(__FILE__);
        }
        else {
            
highlight_file(__FILE__);
        }
        exit;
    }
    
    
// These get_pass() and decrypt() functions are what it is all about. To
    // encrypt data, simply use:
    //     $encrypted = random_bytes(strlen($data));
    //     $pass = get_pass($data, $encryption);
    
    
function get_pass($data$decryption) {
        
$password "";
        
        
$textlen strlen($decryption);
        for (
$i 0$i $textlen$i++) {
            
$password .= chr(ord($data[$i]) - ord($decryption[$i]));
        }
        
        return 
$password;
    }
    
    function 
decrypt($data$pass) {
        
$decrypted_text "";
        
        
$textlen min(strlen($data), strlen($pass));
        for (
$i 0$i $textlen$i++) {
            
$decrypted_text .= chr(ord($data[$i]) - ord($pass[$i]));
        }
        
        return 
$decrypted_text;
    }
    
    function 
download($name$data$contenttype "text/plain") {
        
header("Content-type: $contenttype");
        
header("Content-length: " strlen($data));
        
header("Content-disposition: attachment; filename=\"" str_replace('"''\\"'$name) . "\"");
        echo 
$data;
    }
    
    switch (
$_POST["action"]) {
        case 
"passgen":
            
$rand_data file_get_contents($_FILES["randomdata"]["tmp_name"]);
            
$password  get_pass($rand_data$_POST["decryption"]);
            
            
download("password_for_" $_FILES["randomdata"]["name"] . ".key"$password);
            exit;
        
        case 
"decrypt":
            
$rand_data  file_get_contents($_FILES["randomdata"]["tmp_name"]);
            
$password   file_get_contents($_FILES["password"]["tmp_name"]);
            
$decryption decrypt($rand_data$password);
            
            if (isset(
$_POST["view_as_text"]))
                echo 
"<textarea style='width: 580px; height: 78px;'>$decryption</textarea>";
            else
                
download("decryption_for_" $_FILES["randomdata"]["name"] . ".txt"$decryption);
            
            exit;
        
        case 
"multipass":
            if (isset(
$_FILES["inputfile"]["tmp_name"]) || !empty($_POST["inputtext"])) {
                if (!empty(
$_POST["inputtext"])) {
                    
$inputdata $_POST["inputtext"];
                    
$inputname "secret_message";
                }
                else {
                    
$inputdata file_get_contents($_FILES["inputfile"]["tmp_name"]);
                    
$inputname $_FILES["inputfile"]["name"];
                }
            }
            else {
                die(
"No file or message given to encrypt");
            }
            
            if (
strlen($inputdata) == 0)
                die(
"Empty file or text was given.");
            
            
$inputlength strlen($inputdata);
            
$encrypted_file openssl_random_pseudo_bytes($inputlength);
            
$zippath "data/" sha1($_SERVER["REMOTE_ADDR"] . openssl_random_pseudo_bytes(5));
            
            
$zip = new ZipArchive();
            
$zip->open($zippathZIPARCHIVE::CREATE);
            
            
$zip->addFromString($inputname ".encrypted"$encrypted_file);
            
$zip->addFromString("the_real_key.key"get_pass($encrypted_file$inputdata));
            
            
$i 0;
            foreach (
$_POST["text"] as $text) {
                
$i++;
                if (
strlen($text) > $inputlength) {
                    
cleanupAndExit($zip$zippath"Error: A decryption can't be longer than the original file.");
                }
                
$zip->addFromString("decryption_$i.key"get_pass($encrypted_file$text));
            }
            
            
$zip->close();
            
            if (
headers_sent()) { // Something went wrong, apparently.
                
cleanupAndExit("none"$zippath"Unknown error occured.");
            }
            
            
header("Content-type: application/octet-stream");
            
header("Content-disposition: attachment; filename=\"secrypt.zip\"");
            
header("Content-length: " filesize($zippath));
            
            
$fid fopen($zippath"r");
            do {
                
$line fread($fid1024 100);
                echo 
$line;
            } while (
$line != false && !empty($line) && $zomgrmbl++ < 1000);
            
fclose($fid);
            
            
unlink($zippath);
            
            exit;
    }
    
    function 
cleanupAndExit($tmpziphandle "none"$tmpzippath$message "") {
        if (
$ziphandle != "none")
            
$tmpziphandle->close();
        
        
unlink($tmpzippath);
        
        if (
$message != "") {
            die(
"<br>\n" $message);
        }
        
        exit;
    }
    
    if (
count($_POST) > 0) {
        die(
"Not yet implemented.");
    }
?>
<!DOCTYPE html>
<html>
    <head>
        <title>SeCrypt :: Lucb1e.com</title>
        <style>
            body {
                font-family: Arial;
                font-size: 11pt;
                padding-bottom: 150px;
            }
            .invisibility-cheat {
                display: none;
            }
            .some-block {
                width: 650px;
                padding: 15px 10px 15px 10px;
                margin: 5px auto 5px auto;
                border: 5px solid #E0E0F0;
            }
            .new-block {
                border: 5px solid #B0B0FF;
            }
            .noborder {
                border: none;
            }
        </style>
    </head>
    <body>
        <noscript>
            <h3>It's not gonna work without Javascript... :(</h3>
            This page is an encryption/decryption tool, so without Javascript it'll have a hard time converting things.
            <br><br><hr>
        </noscript>
        <?php 
            
if ($_SERVER["HTTPS"] == "off" || empty($_SERVER["HTTPS"])) {
                
?>
                <div class="some-block new-block">
                    Note: https is turned off. <a href="https://lucb1e.com/rp/php/secrypt/">Secure your connection.</a>
                </div>
                <?php 
            
}
        
?>
        <div id="welcome" class="invisibility-cheat">
            <b>This tool, Secrypt, does two things:</b>
            <ul style="margin-bottom: 15px;">
                <li>Encrypt data with multiple passwords. One is real, other passwords appear to work but give fake data</li>
                <li>Generate a password for data that is not encrypted</li>
            </ul>
            <b><a href="https://www.youtube.com/watch?v=9ypUraYdOrc" target="_blank">Watch a quick demonstration on Youtube</a></b><br/>
            <br/>
            <b>Why would you want to do this?</b><br/>
            More and more governments are writing laws to enforce suspects to give up their passwords. This would
            not be so bad, weren't it for the fact that they are <i>suspects</i>. They may not have done anything. So what
            if they forgot their password? Or store data that looks encrypted, but is simply <a href="http://falkvinge.net/2012/07/12/in-the-uk-you-will-go-to-jail-not-just-for-encryption-but-for-astronomical-noise-too/" target="_blank">random</a>?<br/>
            <br/>
            The law is already in effect in Great Britain. If you don't tell your password for anything they
            think is encrypted, you face up to 5 years of jail. Right now, Dutch lawmakers are looking to implement something similar.<br/>
            <br/>
            That's why I made this tool. It generates passwords for random data (or data that otherwise looks encrypted), and can also
            be used to to protect real data by generating multiple passwords for one file. One of the passwords is
            the real one, others result in fake data.<br/>
            <br/>
            What if the police thinks you have a second password? Simple: you give them another fake. There is
            no way for them to know how many password you've generated. Or perhaps you've already complied to
            the law by providing one.<br/>
            <br/>
            <br/>
            <b>So, what do you want to do?</b>
            <ul style="margin-top: 8px;">
                <li><a href="https://www.youtube.com/watch?v=9ypUraYdOrc" target="_blank">Watch the demonstration on Youtube</a>
                    <br/>&nbsp;</li>
                <li><a href="javascript: gui_passgen();">Generate a password for a file that is not encryped</a></li>
                <li><a href="javascript: gui_multipass();">Encrypt data with multiple passwords</a></li>
                <li><a href="javascript: gui_decrypt();">Decrypt data with a password</a>
                    <br/>&nbsp;</li>
                <li><a href="javascript: gui_moreinfo();">View some more info</a></li>
                <li><a href="?source">View the source code</a></li>
                <li><a href="//lucb1e.com/!about">Contact me</a></li>
            </ul>
        </div>
        <div id="main"></div>
        <div id="moreinfo" class="invisibility-cheat">
            Okay, let's dive a little deeper into how this works. Typically in a symmetric encryption scheme, we have three things:
            <ul>
                <li>Data that you want to keep private or secret (referred to as "the data" or "the original")</li>
                <li>The encryption of this data ("encryption")</li>
                <li>Something that unlocks the encryption ("key" or "password")</li>
            </ul>
            With the data and key you can generate the encryption. With the encryption and key you can generate the data.
            And with Secrypt, you can also generate the key using the original and the encryption.<br/>
            <br/>
            Because the data is private, you'll want to delete it and store the encryption and key seperately.<br/>
            <br/>
            Keep in mind that encryption + key = data.<br/>
            Data is the decryption (because after using the key on the encryption, you can call it the decryption).<br/>
            So to have multiple keys for one encryption, you will also have multiple versions of the data, and one of
            these versions is the original one. Therefore you need to tell the algorithm which decryptions you want the
            keys to have. One key will unlock the original data, the other keys will unlock whatever you want them to.<br/>
            <br/>
            The encryption and the correct key are both the same length as the original data. If you generate another decryption
            which is shorter or longer than the data, it's trivial to see it's a fake. Why? If you give the encryption with
            a fake key to someone, they know the length of the encryption, and thus the length of the original data, and thus
            how long a key <i>should</i> be. This is why it's smart to make all decryptions the same length as the encryption,
            then all keys will have the same length and it's impossible to know (assuming that your decryptions make sense)
            whether any key is a fake or not.<br/>
            <br/>
            If you have any further questions, feel free to <a href="//lucb1e.com/!about">contact me</a>!
        </div>
        <div id="encrypt" class="invisibility-cheat"></div>
        <div id="decrypt" class="invisibility-cheat">
            <b>Decrypt your file with a password</b><br/>
            Or someone else's file, of course.<br/>
            <br/>
            <form method="POST" enctype="multipart/form-data" action="" target="frame6" onsubmit="temporaryDisable($('btnDecrypt'));return true;">
                <input type="hidden" name="action" value="decrypt"/>
                The encrypted or random data:<br/>
                <input type="file" name="randomdata"/><br/>
                <br/>
                The key or password file:<br/>
                <input type="file" name="password"/><br/>
                <br/>
                <label for="view_as_text"><input type="checkbox" name="view_as_text" id="view_as_text" checked /> View as text</label> (otherwise it will download as file)<br/>
                If you download as file, you probably need to rename the file. If it should be an image, make the name end in .jpg, or whatever it originally was.<br/>
                <br/>
                <input type="submit" value="Decrypt!" id="btnDecrypt" />
            </form>
            <iframe style="width: 600px; height: 100px; border: 0;" frameborder="no" name="frame6" id="frame6"></iframe>
        </div>
        <div id="passgen" class="invisibility-cheat">
            <b>Generate a decryption for some file</b><br/>
            Note that the file can technically be anything: random data, encrypted data, an unencrypted Word document, images...<br/>
            <br/>
            <form method="POST" enctype="multipart/form-data" action="" target="_blank">
                <input type="hidden" name="action" value="passgen"/>
                The file you want a password for:<br/>
                <input type="file" name="randomdata"/><br/>
                <br/>
                What text do you want it to decrypt to?<br/>
                <textarea name="decryption" style="width: 560px" rows="4"></textarea><br/>
                <br/>
                <input type="submit" value="Download password"/>
            </form>
        </div>
        <div id="multipass" class="invisibility-cheat">
            <b>Encrypt a file and generate multiple passwords</b><br/>
            Note: I cannot stand in for the safety of this tool for protecting real data; it has not been analysed by anyone besides myself.
            I believe it is fairly safe, albeit impractical with large amounts of data, but you still shouldn't ever trust a single person's opinion
            on cryptography. Doing crypto correctly is hard.<br/>
            <br/>
            Perhaps it's an idea to encrypt your data with AES or something, then using the "Generate a password for a file that is not encrypted"-tool
            to obtain one or more fake passwords for it.<br/>
            <br/>
            <form method="POST" enctype="multipart/form-data" action="" target="frame5">
                <input type="hidden" name="action" value="multipass"/>
                <b>1. File or message to encrypt</b><br/>
                If you want to encrypt a file:<br/>
                <input type="file" name="inputfile"/><br/>
                <br/>
                If you want to encrypt a message:<br/>
                <textarea style="width: 590px; height: 90px;" name="inputtext"></textarea><br/>
                <br/>
                <b>2. Fake decryptions</b>
                <div id="decryptions"></div>
                <input type="button" onclick="addDecryption();" value="Add a decryption"/><br/>
                <br/>
                <b>3. Result</b><br/>
                The download will be a zip file with the encryption, the correct key, and another key for every decryption you've added.
                You should extract the zip and store the encryption seperately from any keys (a good place for keys might be a usb-stick).
                You might also want to rename the files so that you know which is which.<br/>
                <input type="submit" value="Download"/>
            </form>
            
            <iframe style="width: 600px; height: 100px; border: 0;" frameborder="no" name="frame5" id="frame5"></iframe>
            
            <!-- This div will be added to $("decryptions"). -->
            <div id="add-decryption" class="invisibility-cheat">
                Enter decryption (#__N__)<br/>
                <textarea style="width: 590px; height: 90px;" name="text[]"></textarea><br/>
            </div>
        </div>
        <script>
            function $(id) {
                return document.getElementById(id);
            }
            function n(name) {
                return document.getElementsByName(name)[0];
            }
            function newDiv(appendObj) {
                var mydiv = document.createElement("div");
                appendObj.appendChild(mydiv);
                return mydiv;
            }
            $("welcome").className = "some-block";
            var multidec_num = 0;
            function scroll(to, max) {
                if (max == true)
                    to = Math.max(to, document.body.scrollTop);
                
                document.body.scrollTop = to;
            }
            function show(id) {
                $(id).className = "some-block new-block";
                setTimeout("$('" + id + "').className = 'some-block';", 800);
                scroll(300, true);
            }
            function hideAll() {
                $("passgen").className = "invisibility-cheat";
                $("decrypt").className = "invisibility-cheat";
                $("multipass").className = "invisibility-cheat";
                $("moreinfo").className = "invisibility-cheat";
            }
            function addDecryption() {
                multidec_num++;
                var child = newDiv($("decryptions"));
                child.innerHTML = $("add-decryption").innerHTML.replace("__N__", multidec_num);
                child.className = "";
            }
            function gui_passgen() {
                hideAll();
                show("passgen");
            }
            function gui_decrypt() {
                hideAll();
                show("decrypt");
            }
            function gui_multipass() {
                hideAll();
                show("multipass");
            }
            function gui_moreinfo() {
                hideAll();
                show("moreinfo");
            }
            function temporaryDisable(submitbtn) {
                submitbtn.disabled = true;
                
                setTimeout(function() {
                    submitbtn.removeAttribute("disabled");
                }, 2500);
            }
        </script>
    </body>
</html>