2

I have read so many topics on this very subject by now, I can't understand where the issue could possibly lie. I am encrypting part of a URL from a C# winform application. I then want to read in the URL using php and decrypt the url (all using base-64). I do have some code to shrae:


Code to encrypt URL (C#):

public static string Base64Encode(string str)
{
    byte[] encbuff = Encoding.UTF8.GetBytes(str);
    return System.Web.HttpServerUtility.UrlTokenEncode(encbuff);
}

Decrypt a section of the URL:

Base64Encode("CND0311J4S68CCU Ver. F.0BHPQOEM - f");

Returns:

Q05EMDMxMUo0UzY4Q0NVIFZlci4gRi4wQkhQUU9FTSAtIGY1

Code to decrypt URL (PHP):

echo base64_decode("Q05EMDMxMUo0UzY4Q0NVIFZlci4gRi4wQkhQUU9FTSAtIGY1");

Returns:

CND0311J4S68CCU Ver. F.0BHPQOEM - f5

So, where is the extra "5" at the end of the return coming from? I cannot figure this out for the life of me, quite frustrating as you could imagine.

I appreciate any help with this - as well as any suggestions!

Thank you,

Evan

Community
  • 1
  • 1
  • StringToByte is you own function - it may (likley) add extra byte. Post the code that actually shows the error... – Alexei Levenkov Sep 16 '11 at 18:13
  • I get Q05EMDMxMUo0UzY4Q0NVIFZlci4gRi4wQkhQUU9FTSAtIGY= when I base64 encode the string you supplied. http://www.motobit.com/util/base64-decoder-encoder.asp - URL encoded it looks like: Q05EMDMxMUo0UzY4Q0NVIFZlci4gRi4wQkhQUU9FTSAtIGY%3D – Andrew Church Sep 16 '11 at 18:15
  • @Alexei I updated to use Encoding.UTF8.GetBytes - same error –  Sep 16 '11 at 18:17
  • @Andrew this is not base64 encoding exactly. It's a URL safe version of base-64. –  Sep 16 '11 at 18:17
  • That's not called encryption, but encoding. `System.Web.HttpServerUtility.UrlTokenEncode` is not base64 encode, just similar. See my updated answer. – hakre Sep 16 '11 at 18:18

2 Answers2

4
"CND0311J4S68CCU Ver. F.0BHPQOEM - f"

encoded as base64 is not:

Q05EMDMxMUo0UzY4Q0NVIFZlci4gRi4wQkhQUU9FTSAtIGY1

Probably something else is adding the 1 at the end, because

echo base64_decode("Q05EMDMxMUo0UzY4Q0NVIFZlci4gRi4wQkhQUU9FTSAtIGY");

gives you what you're looking for. And that something adding it is in fact System.Web.HttpServerUtility.UrlTokenEncode. The issue is the following (from MSDN):

This (System.Web.HttpServerUtility.UrlTokenEncode) does not use a standard encoding. It encodes with - and _ characters which is standard. It also removes the = signs. But rather than simply removing them (they're not necessary to decode the string), it replaces them with a digit (0, 1, 2) indicating the number of = signs that were removed.

So go for it (Demo):

<?php

$urltoken = "Q05EMDMxMUo0UzY4Q0NVIFZlci4gRi4wQkhQUU9FTSAtIGY1";
echo urltoken_decode($urltoken);

function urltoken_decode($token)
{
    return base64_decode(substr($token, 0, -1));
}

The function is pretty rough and could be improved to actually deal with it more specifically (Demo2):

function urltoken_decode($token)
{
    $len = strlen($token);
    if (!$len)
       return $token;

    $digit = $token[$len-1];
    if (!in_array($digit, range(0,2)))
    {
        throw InvalidArgumentException(sprintf('Invalid end digit (%s).', $digit));
    }
    return base64_decode(substr($token, 0, -1));
}
hakre
  • 193,403
  • 52
  • 435
  • 836
  • is it guaranteed that a number will be appended to the encoded string? Even if nothing is replaced, it will append '0'? –  Sep 16 '11 at 18:20
  • According to the user-comment it is. There will be no number if the string is empty however according to that comment which is what I've used as spec. You should further test it. I've updated the function to better reflect the cases and to throw exceptions for the cases which are unspecified to have it a bit more strict. Hope this helps. For the real specification you need to ask microsoft to review the sourcecode. Ha Ha Ha :) - Otherwise you some other function like http://msdn.microsoft.com/en-us/library/system.convert.tobase64string.aspx – hakre Sep 16 '11 at 18:30
  • Would this would work just as well if from the C# side I did: string encodedURL = HttpServerUtility.UrlTokenEncode(encbuff); return encodedURL.Substring(0, encodedURL.Length - 1); Just gets rid of the last digit. –  Sep 16 '11 at 18:32
  • Well maybe you just want to use the right function then? - http://msdn.microsoft.com/en-us/library/system.convert.tobase64string.aspx – hakre Sep 16 '11 at 18:34
  • that function actually will not work as some of the extra characters added (+, ==, etc.) mess with the URL when being read through PHP. –  Sep 16 '11 at 18:35
  • Then urlencode it after you have base64 encoded it, or am I missing something? – hakre Sep 16 '11 at 18:37
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/3538/discussion-between-evan-and-hakre) –  Sep 16 '11 at 18:38
  • 1
    The last digit will always be added if the result is not null or empty string. See here for the implementation details: http://referencesource.microsoft.com/System.Web/R/0e3cb83cf51ca334.html – Herman Jul 02 '14 at 22:56
0

Interesting - when I encode "CND0311J4S68CCU Ver. F.0BHPQOEM - f" at this site (using JavaScript) it encodes as "Q05EMDMxMUo0UzY4Q0NVIFZlci4gRi4wQkhQUU9FTSAtIGY". If I decode "Q05EMDMxMUo0UzY4Q0NVIFZlci4gRi4wQkhQUU9FTSAtIGY1" I get the extra 5 on the end. Apparently the problem is on the encoding end - maybe try outputting the value you're encoding just before it's passed to the base64 encoder to make sure it's exactly what you think it is?

Surreal Dreams
  • 26,055
  • 3
  • 46
  • 61
  • Yes, I did. Feel free to use the encryption function I posted above to test though. –  Sep 16 '11 at 18:15