1

I need to obfuscate sensitive information like email addresses written to visitor cookies on my website and was hopeful about RC4. But I had written a simple test to compare each character in strings output from a standard RC4 routine against all known acceptable characters for use in cookies, based on the documentation I pulled from https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie After several random tests, I concluded that RC4 strings could cause issues if written to cookie values 'as is".

Of course, I could use something simpler like base64, since the cookies would be stored on the visitor's own system. But I'd rather use something stronger. I'd be leery or re-writing an RC4 routine to "stick to" the allowed characters, and know I could still recover the original data. But before I even try, I'd like to think it has been "done" already. But I have not been able to find such a thing.

For reference, this is the RC4 routine I'd be starting with (PHP)...

/*
 * RC4 symmetric cipher encryption/decryption
 *
 * @license Public Domain
 * @param string key - secret key for encryption/decryption
 * @param string str - string to be encrypted/decrypted
 * @return string
 */
function rc4($key, $str) {
    $s = array();
    for ($i = 0; $i < 256; $i++) {
        $s[$i] = $i;
    }
    $j = 0;
    for ($i = 0; $i < 256; $i++) {
        $j = ($j + $s[$i] + ord($key[$i % strlen($key)])) % 256;
        $x = $s[$i];
        $s[$i] = $s[$j];
        $s[$j] = $x;
    }
    $i = 0;
    $j = 0;
    $res = '';
    for ($y = 0; $y < strlen($str); $y++) {
        $i = ($i + 1) % 256;
        $j = ($j + $s[$i]) % 256;
        $x = $s[$i];
        $s[$i] = $s[$j];
        $s[$j] = $x;
        $res .= $str[$y] ^ chr($s[($s[$i] + $s[$j]) % 256]);
    }
    return $res;
}

Also for reference, based on the mozilla.org reference I linked, I built this simple javascript function to test output strings, and count the errors (errors meaning illegal chars) in a string.

function cookieSafe(str) {
    var okchars = "!#$%&'()*+-./:<=>?@[]^_`{|}~ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
    var letterNumber = /^[0-9a-zA-Z]+$/;
    var s;
    var errors =0;

    for (var i = 0; i < str.length; i++) {
        s = str.substr(i,1);
        if (okchars.indexOf(s) > -1) continue;
        errors +=1;
        }
    return errors;
    }

Thanks for any help, and thanks for NOT down-voting. I'd rather be counseled to properly fix or delete my question than be "banned" again.

Randy
  • 301
  • 2
  • 11
  • 2
    Encrypt it with RC4, then encode it with base64 to make it safe for cookie. – Barmar Jun 29 '19 at 15:12
  • Yes. And I almost deleted my question due to the extent it exposes my inability to see the obvious. Even after re-reading my post the morning after writing it, I realized the answer was right within my question. Bug "DUH" moment for me! I'm almost ready to down-vote my own question here. But thanks for the confirm. Upon testing I see that RC4 followed by base64_encode makes a perfect cookie value, and bas64_decode followed by RC4 never fails to recover original source data. My apologies to everyone. :-( – Randy Jun 29 '19 at 19:10
  • @Barmar By the way, for completeness I had to mention that after doing base64 encoding, I found some of the characters output by base 64 are problematic , for different reasons. So after RC4, and after base64, I've written a "fix64(): to replace questionable ones: (1) replace "+" with "*" (because + won't be seen in a $_COOKIE array string!), replace "/" with "_", so just in case you create a directory with the string, you won't be trying to mkdir 2 at once. There are a few others like "=" and "-" that can cause unexpected issues too. Fortunately, plenty of cookie safe chars to choose from. – Randy Jul 11 '19 at 20:27

0 Answers0