-2

I'm trying to pass a download URL from page 1 to page 2 in a GET request.

Page 1 gets the raw URL through the database, then encrypts the URL and makes it available on the site. When it's passed through the URL, page 2 decrypts the URL and downloads the file.

The URL looks like this currently:

https://example.com/download.php?dl=x6%1A%D8j%C4%D2%9Cx%8FA%8B%29%23Y%D9%D6%B4%DE8%18%2C%7B%F4%86l%B0%0A+%D3%B1%01I%CFo%FF%BA%9C%22%A1%08%11%DB%12%282%DEi%B5%CA%14K%FF%21%CB%F3%9D%3C9f%3C%09%FA9%BB%BD%C9%B2%275%F0%06%A2%80%08h%A7f%8C%87%28%A4%A5%99%A9%A9%FA%D6f%C5%CA%9B%81.%92%CD%89%FA3%5C%0C%F0%ED%F6%D9%1E%B9%D0%B1%CFSA%F4%95k%1EZ%D1%3A%D4H%1D%93%40%087%92%88%C3%A5p%C7WH%FA%CF%9D%BAKd%A0%9A%D7a6%80%5Ex%A5%87%07AK%D7%5BQ%10%98%07%7E%82%9A%BA9%25%D5%EA%03%FD%C2%9A%22%8FBW%94k%D8T%93%F5%E3%D7-

It contains a lot of %%% because it's urlencoded, is there a way to change this to make the URL less long and make it look less messy, but keep it safe as it is now?

Hope someone can help me out.

This is the encryption and decryption script:

define("ENCRYPTION_KEY", "ducksandpizza");

function encrypt($pure_string, $encryption_key) {
    $iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
    $encrypted_string = mcrypt_encrypt(MCRYPT_BLOWFISH, $encryption_key, utf8_encode($pure_string), MCRYPT_MODE_ECB, $iv);

    return urlencode($encrypted_string);
}

function decrypt($encrypted_string, $encryption_key) {
    $iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
    $decrypted_string = urldecode($encrypted_string);
    $decrypted_string = mcrypt_decrypt(MCRYPT_BLOWFISH, $encryption_key, $encrypted_string, MCRYPT_MODE_ECB, $iv);

    return $decrypted_string;
}

//$encrypted = encrypt($_GET['dl'], ENCRYPTION_KEY);
$decrypted = decrypt($_GET['dl'], ENCRYPTION_KEY);

//echo 'encrypted: ' . $encrypted . '<br>';
echo 'decrypted: ' . $decrypted . '<br>';
Mitch
  • 183
  • 1
  • 10
  • Use `base64_encode()` instead of `urlencode()` – Alex Howansky Nov 08 '17 at 19:20
  • 7
    What a horrible concept to protect data! – arkascha Nov 08 '17 at 19:21
  • Have many problems in this code. The `mcrypt` is deprecated. Also, the ECB mode does not guaranty the integrity of the message. The attacker can change the encrypted data, and you need the same IV to decrypt. The last, you are using ECB.... – Inkeliz Nov 08 '17 at 19:22
  • 2
    _"I'm trying to pass a download URL from page 1 to page 2 in a GET request"_ - replace "a GET request" with "the session", and well done! Makes the en-de-cryption nonsense superfluous as well. – CBroe Nov 08 '17 at 19:23
  • Do you have to use GET? Cookies, Sessions, or POST requests work and don't clutter up the URL. – Forbs Nov 08 '17 at 19:24
  • @Forbs In my case GET is certainly one of the better ways for this, yes. – Mitch Nov 08 '17 at 19:26
  • Then pretty much any kind of encryption will not help. Encryption increases the number of bytes of any data due to it's nature. Only hashing reduces bytes but you lose the ability to go back. `base64_encode` looks prettier than `url_encode` if that's what you are after – Forbs Nov 08 '17 at 19:29
  • _"In my case GET is certainly one of the better ways for this"_ - based on ...? Give us some details ... – CBroe Nov 08 '17 at 19:31
  • @Forbs Good encryption should not be adding data to your input. It will not reduce size unless the algorithm implements compression as well. – Alex Barker Nov 08 '17 at 19:32
  • @AlexBarker yes, that is true, but Poster is stuck in the URL, so the encryption is limited to printable characters. I mean rolling the char Id will achieve that, but isn't really trying to 'encrypt' anything. But it's way off topic as I don't think OP is really thinking of encryption properly. – Forbs Nov 08 '17 at 19:34
  • @Forbs _"but Poster is stuck in the URL"_ - well they seem to be _stuck on_ it, but so far we not heard any reasoning behind that ... as long as not indicated differently, I think it is fair to assume that _"page 1 to page 2"_ means pretty much withing the same site, so I don't see why they would actually not have a _better_ choice than GET. – CBroe Nov 08 '17 at 19:41
  • @CBroe , exactly, that's why I pointed out 3 other ways to store non visible variables. – Forbs Nov 08 '17 at 19:41
  • Wish for encryption means something to hide, something to hide means better not let it leave the server to begin with. A.k.a. sessions. – CBroe Nov 08 '17 at 19:43

2 Answers2

0

Use some type of compression on the unencrypted data, like gzcompress() and then pass that to your encryption method, and the output of that to base64_encode. Base64 encoding will still increase the overall size, but not as much as url encode does.

Alex Barker
  • 4,316
  • 4
  • 28
  • 47
0

While using base64_encode() isn't necessarily a bad idea, no one has mentioned that stock base64 encoding is not URL-safe as it uses the characters significant in URL syntax.

However, there's a variant that is safe that's used for encoding JWT tokens:

function base64url_encode($bin) {
    return str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($bin));
}

function base64url_decode($str) {
    return base64_decode(str_replace(['-', '_'], ['+', '/'], $str));
}

You should also bear in mind the GET requests are subject to length restrictions which vary between HTTP server implementations and languages. You'll probably want to use something like gzcompress() as suggested in the comments, but more likely you should be passing this data in a POST instead.

Sammitch
  • 30,782
  • 7
  • 50
  • 77