Answered Base64 padding character issue

  • Tuesday, October 04, 2005 7:18 PM
     
     
    The problem I'm having is if I'm trying to take a string (say a password) that's 5 characters long, Base64 works on strings that are a length of a multiple of 4, so 4 bytes long, 8, 12, etc...  But from the description of ConvertFromBase64, if it's not a multiple of 4, you need to pad it to be that long.  But alas, it will only pad up to 2 "pad" characters, so my 5-character password, plus 2 "pad" characters makes 7, not 8.  Furthermore, ConvertFromBase64 will ignore traditional whitespace characters for counting the multiple of 4.

    This leaves me to either make a generic "Q000PFGG" string as an arbritary "pad" character, and when i look at the string later, if it matches i remove that occurance.  But my question is how come you're not allowed 3 whitespace characters for Base64 and maybe someone will have a workaround.


    Here is the description of System.Convert.FromBase64String from Feb2005 of MSDN:

    s is composed of base 64 digits, white space characters, and trailing padding characters. The base 64 digits in ascending order from zero are the uppercase characters 'A' to 'Z', lowercase characters 'a' to 'z', numerals '0' to '9', and the symbols '+' and '/'.

    The white space characters are tab, blank, carriage return, and newline. An arbitrary number of white space characters can appear in s because all white space characters are ignored.

    The valueless character, '=', is used for trailing padding. The end of s can consist of zero, one, or two padding characters.


    Here is my workaround code so far (throws an Base64 invalid character exception if sData.Length needs 3 whitespace characters [iReminderValue = 3]):



            /// <summary>
            /// Character used for padding strings
            /// </summary>
            private static readonly char PAD_CHARACTER = '=';


                #region Determine Padding

                //determine how many characters to pad (Base64 needs to have a length of a multiple of 4)
                int iRemainderValue = 0;

                //if the length isn't already a multiple of 4, determine the number of characters needed to make it so
                if( 0 != (sData.Length % 4) )
                    iRemainderValue = 4 - (sData.Length % 4);

                //make sure the string is at least 8 characters)
                sData = sData.PadRight( sData.Length + iRemainderValue, PAD_CHARACTER);

                #endregion
     
                //return the encrypted data in string format
                return System.Convert.ToBase64String( EncryptData( System.Convert.FromBase64String( sData ) ) );

     

Answers

  • Friday, October 07, 2005 1:02 PM
    Moderator
     
     Answered
    I think you misunderstand what your code is doing and what you wanted it to do.  In your case you want to take an arbitrary string and Base64 encode it.  Your code however is taking a Base64 string and attempting to decode it.  I assume the problem you're having is that either the code is throwing an exception or returning invalid data. 

    Your last line of code is doing the following:
    1.  Take sdata and translate it from a Base64 string to a normal string
    2.  Encrypt the string.
    3.  Convert the encrypted string to a Base64 string.

    I believe instead you want to entirely skip step 1 because you are dealing with a raw user string of arbitrary length.  Therefore you should just encrypt the string and then use ToBase64String to convert it to a Base64 string. 

    The whole padding thing is specifying the requirements of a properly formatted Base64 string.  Therefore when you call FromBase64String the specified string must be properly formatted and a proper length.  To convert to Base64 you can use any string length.  You don't need to pad the string.  If you look at the encoded string you'll see the '=' signs that the documentation you read is mentioning.

    As a side note I wouldn't recommend Base64 encoding a password because anybody can easily decode it.  You should instead use one of the cryptographic providers.

    Michael Taylor - 10/7/05

All Replies

  • Friday, October 07, 2005 1:02 PM
    Moderator
     
     Answered
    I think you misunderstand what your code is doing and what you wanted it to do.  In your case you want to take an arbitrary string and Base64 encode it.  Your code however is taking a Base64 string and attempting to decode it.  I assume the problem you're having is that either the code is throwing an exception or returning invalid data. 

    Your last line of code is doing the following:
    1.  Take sdata and translate it from a Base64 string to a normal string
    2.  Encrypt the string.
    3.  Convert the encrypted string to a Base64 string.

    I believe instead you want to entirely skip step 1 because you are dealing with a raw user string of arbitrary length.  Therefore you should just encrypt the string and then use ToBase64String to convert it to a Base64 string. 

    The whole padding thing is specifying the requirements of a properly formatted Base64 string.  Therefore when you call FromBase64String the specified string must be properly formatted and a proper length.  To convert to Base64 you can use any string length.  You don't need to pad the string.  If you look at the encoded string you'll see the '=' signs that the documentation you read is mentioning.

    As a side note I wouldn't recommend Base64 encoding a password because anybody can easily decode it.  You should instead use one of the cryptographic providers.

    Michael Taylor - 10/7/05
  • Monday, November 07, 2005 9:15 PM
     
     
    Sorry for the late reply; I had Alert Me on and it didnt send a reply.

    Anyways I understood what my code was doing (had to do it from the constraints of the EncryptData() function and such.  My original problem is with the constraints of the Base64 class, where it will only add padding up to 2 characters.  What if you need 3?