views:

95

answers:

2

Given an input string (will actually be an integer value) and an encryption key, I need to encrypt the input string in such a way that the resulting string is:

  1. URL safe (my permitted URI characters is currently: a-z 0-9~%.:_-)
  2. Filename safe (meaning, it only uses valid directory/filename characters)
  3. FTP account username safe
  4. Email account username safe

Then, given the encrypted string and the same encryption key, decrypt the the string into its unencrypted form.

This is not intended to be a security measure. Implementation needs to be in PHP. Thanks.

EDIT 1 (the decoding still includes undesirable characters; plus, there is no way to make sure the resulting encrypted string is within a certain length):

function decrypt($string, $encryption_key)
{
    assert(isset($string) === TRUE);
    assert(isset($encryption_key) === TRUE);

    $result = '';
    $string = base64_decode($string);

    for ($i = 0; $i < strlen($string); $i++)
    {
        $char    = substr($string, $i, 1);
        $keychar = substr($encryption_key, ($i % strlen($encryption_key)) - 1, 1);
        $char    = chr(ord($char) - ord($keychar));
        $result .= $char;
    }

    return $result;
}


function encrypt($string, $encryption_key)
{
    assert(isset($string) === TRUE);
    assert(isset($encryption_key) === TRUE);

    $string = (string) $string;
    $result = '';

    for ($i = 0; $i < strlen($string); $i++)
    {
        $char    = substr($string, $i, 1);
        $keychar = substr($encryption_key, ($i % strlen($encryption_key)) - 1, 1);
        $char    = chr(ord($char) + ord($keychar));
        $result .= $char;
    }

    return base64_encode($result);
}
+1  A: 

Consider encryption and encoding as two distinct and unrelated steps. In one direction you encrypt plaintext bytes to get cipher bytes, then encode the bytes to get a string. The other direction you decode the string to get ciphertext bytes, then decrypt the ciphertext bytes to get plaintext bytes.

Your requirements can be most simply satisfied by using a simple hex, or base 16, encoder that converts a byte into two hex characters. If encoding space efficiency is absolutely critical, you can implement your own base-62 encoder that uses only upper and lower case letters and digits. It will be slower and possibly uglier than hex encoding.

EDIT 1:

If base-64 encoding produces acceptable strings all the better. Base-64 uses 4 characters to encode 3 bytes. So if you are limited to 64 characters then you cannot encode more than (64/4) * 3 = 48 bytes.

GregS
@GregS, that's a good idea. I have an encrypt/decrypt function already. My problem was that I was getting undesirable characters. Is there a way to make sure encoding results in a string no greater than a certain length? (e.g. the local part of an email address apparently is limited to 64 characters only: http://en.wikipedia.org/wiki/Email_address#Specification)
StackOverflowNewbie
@GregS, I edited the original post. Any suggestions how I can improve the encoding?
StackOverflowNewbie
+1  A: 

For encrypting, depending on your security demands, the mcrypt_encrypt (http://us2.php.net/manual/en/function.mcrypt-encrypt.php) functions may be simple enough.

Once you get it working, then, if you need more security you can change the encryption function as the rest of your program won't care.

Once you encrypt you can use base-64 encoding (http://us2.php.net/manual/en/function.base64-encode.php), which is a known pattern that is well-tested.

Since you are encrypting an int, which is at most 8 bytes long, any length of key should be fine, in order to have a known size result your key needs to >= 8 bytes.

I would suggest you don't write your own encryption algorithm, as it will be insecure, and there are many out there to meet your needs, depending on whatever other requirements you have. As was mentioned, you can work back and determine the size that you want the encoded string to be, that will tell you how many bytes the encrypted result can be. Then, you can work out the size of the key in order to get the size of the encrypted message.

If you want to encrypt a string of arbitrary length, then the previous paragraph will be wrong, as the size of the encrypted message won't be known.

James Black
Just using mcrypt is not enough. You must know how to use it. Most of the code I see there that uses mcrypt reuses the same IV all the time...
Artefacto
@Artefacto - I included the link to the manual as I find the comments by others to be better than the original documentation, though it takes a while to read through. But, how to use mcrypt would be a different question, also, as then he could show how he is using it, and others can then show how to do it more securely.
James Black