Bug 17640 - System.FormatException: Invalid character found
Summary: System.FormatException: Invalid character found
Alias: None
Product: Android
Classification: Xamarin
Component: General ()
Version: 4.10.1
Hardware: PC Mac OS
: --- normal
Target Milestone: ---
Assignee: Sebastien Pouliot
Depends on:
Reported: 2014-02-06 12:24 UTC by Allie Miller
Modified: 2014-02-07 14:19 UTC (History)
1 user (show)

Is this bug a regression?: ---
Last known good build:

Test Project (12.88 KB, application/zip)
2014-02-06 12:24 UTC, Allie Miller

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.

Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:

Description Allie Miller 2014-02-06 12:24:38 UTC
Created attachment 5991 [details]
Test Project

Report based on forum thread: http://forums.xamarin.com/discussion/13102/system-formatexception-when-decoding-a-base64string?new=1

When running the attached test project, decoding the Base64 string results in the following error:

Instance    {System.FormatException: Invalid character found.
at (wrapper managed-to-native) System.Convert.InternalFromBase64String (string,bool) <0x0003b>
at System.Convert.FromBase64String (string) <IL 0x00024, 0x0010f>
at o2hilft.StringEncryptionHelper.DecodeBaseString (string) [0x00001] in c:\Users\Marco\Documents\Dev\Xamarin Projects\o2hilft\o2hilft\o2hilft\Helpers\StringEncryptionHelper.cs:70
at o2hilft.WillkommenFragment.OnViewCreated (Android.Views.View,Android.OS.Bundle) [0x00073] in c:\Users\Marco\Documents\Dev\Xamarin Projects\o2hilft\o2hilft\o2hilft\Tabs\WillkommenFragment.cs:91
at Android.App.Fragment.n_OnViewCreated_Landroid_view_View_Landroid_os_Bundle_ (intptr,intptr,intptr,intptr) [0x00019] in /Users/builder/data/lanes/monodroid-mlion-monodroid-4.10.1-branch/d23a19bf/source/monodroid/src/Mono.Android/platforms/android-15/src/generated/Android.App.Fragment.cs:1560
at (wrapper dynamic-method) object.e50f2580-a49f-4a37-8748-44e8a43beba7 (intptr,intptr,intptr,intptr) <IL 0x0001d, 0x0004b>
}   System.FormatException

Versioning Information:
Xamarin.Android: 4.10.2
Visual Studio 2013
Comment 2 Jonathan Pryor 2014-02-06 16:28:38 UTC
I am not able to reproduce the FormatException. Instead, I get a different exception:

> UNHANDLED EXCEPTION: System.Security.Cryptography.CryptographicException: Invalid input block size.
> at System.Security.Cryptography.RijndaelTransform.FinalDecrypt (byte[],int,int) <IL 0x00084, 0x00124>
> at Mono.Security.Cryptography.SymmetricTransform.TransformFinalBlock (byte[],int,int) <IL 0x00038, 0x0007b>
> at System.Security.Cryptography.RijndaelManagedTransform.TransformFinalBlock (byte[],int,int) <IL 0x00009, 0x0003b>
> at System.Security.Cryptography.CryptoStream.FlushFinalBlock () <IL 0x00050, 0x0004b>
> at System.Security.Cryptography.CryptoStream.Dispose (bool) <IL 0x0001d, 0x0003b>
> at System.IO.Stream.Close () <IL 0x00002, 0x0001f>
> at MailTest.StringEncryptionHelper.Decrypt (string) [0x0006c] in /Users/jon/Downloads/bxc-17640/MailTest/MailTest/StringEncryptionHelper.cs:61
> at MailTest.MainActivity.PrepareMail () [0x0008c] in /Users/jon/Downloads/bxc-17640/MailTest/MailTest/MainActivity.cs:75
> at MailTest.MainActivity.<OnCreate>m__0 (object,System.EventArgs) [0x00002] in /Users/jon/Downloads/bxc-17640/MailTest/MailTest/MainActivity.cs:42
> at Android.Views.View/IOnClickListenerImplementor.OnClick (Android.Views.View) <IL 0x00014, 0x00047>
> at Android.Views.View/IOnClickListenerInvoker.n_OnClick_Landroid_view_View_ (intptr,intptr,intptr) <IL 0x00013, 0x0005f>
> at (wrapper dynamic-method) object.3ec586f6-0198-40cb-bba3-bfa5338865d5 (intptr,intptr,intptr) <IL 0x00017, 0x00043>

This is likewise with Xamarin.Android 4.10.2.

Related: It's handy to remove unnecessary dependencies. In this case, Android is an unnecessary dependency -- all the interesting stack frames are in BCL assemblies, and thus we can drastically simplify the test case:

  using System;
  using System.IO;
  using System.Security.Cryptography;
  using System.Text;

  class Demo {
  	public static void Main ()
  		string rgbIVString  = "Kob9rzAGD08kuxGqfr0i";
  		string keyString    =
  		string encryptedText = "ZnJvbW1haWxAdGVzdHNlcnZlci5kZQ==";
  		byte[] encryptedTextBytes = Convert.FromBase64String(encryptedText);

  		var ms        = new MemoryStream();

  		var rijn      = SymmetricAlgorithm.Create();
  		rijn.Padding  = PaddingMode.Zeros;

  		var rgbIV     = Encoding.UTF8.GetBytes(rgbIVString.Substring(0,16)); 
  		var key       = Encoding.UTF8.GetBytes(keyString.Substring(0,32)); 

  		var cs = new CryptoStream(ms, rijn.CreateDecryptor(key, rgbIV),

  		cs.Write(encryptedTextBytes, 0, encryptedTextBytes.Length);


  		Console.WriteLine ("Decrypted: '{0}'", Encoding.UTF8.GetString(ms.ToArray()));

This likewise fails with the ~same stack trace:

> Unhandled Exception:
> System.Security.Cryptography.CryptographicException: Invalid input block size.
>   at System.Security.Cryptography.RijndaelTransform.FinalDecrypt (System.Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount) [0x00082] in /private/tmp/source/bockbuild-mono-3.2.6/profiles/mono-mac-xamarin/build-root/mono-3.2.6/mcs/class/corlib/System.Security.Cryptography/RijndaelManagedTransform.cs:305 
>   at Mono.Security.Cryptography.SymmetricTransform.TransformFinalBlock (System.Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount) [0x00034] in /private/tmp/source/bockbuild-mono-3.2.6/profiles/mono-mac-xamarin/build-root/mono-3.2.6/mcs/class/Mono.Security/Mono.Security.Cryptography/SymmetricTransform.cs:488 
>   at System.Security.Cryptography.RijndaelManagedTransform.TransformFinalBlock (System.Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount) [0x00000] in /private/tmp/source/bockbuild-mono-3.2.6/profiles/mono-mac-xamarin/build-root/mono-3.2.6/mcs/class/corlib/System.Security.Cryptography/RijndaelManagedTransform.cs:96 
>   at System.Security.Cryptography.CryptoStream.FlushFinalBlock () [0x0003d] in /private/tmp/source/bockbuild-mono-3.2.6/profiles/mono-mac-xamarin/build-root/mono-3.2.6/mcs/class/corlib/System.Security.Cryptography/CryptoStream.cs:310 
>   at System.Security.Cryptography.CryptoStream.Dispose (Boolean disposing) [0x0001c] in /private/tmp/source/bockbuild-mono-3.2.6/profiles/mono-mac-xamarin/build-root/mono-3.2.6/mcs/class/corlib/System.Security.Cryptography/CryptoStream.cs:340 
>   at System.IO.Stream.Close () [0x00000] in /private/tmp/source/bockbuild-mono-3.2.6/profiles/mono-mac-xamarin/build-root/mono-3.2.6/mcs/class/corlib/System.IO/Stream.cs:113 
>   at Demo.Main () [0x0007d] in /Users/jon/Downloads/bxc-17640/MailTest/MailTest/m.cs:29
Comment 3 Jonathan Pryor 2014-02-06 16:29:47 UTC
Sebastien: Any idea on what's wrong w/ the code in Comment #2?
Comment 4 Sebastien Pouliot 2014-02-07 10:07:32 UTC
@Jonp I'm not sure I see how this code is related to the original forum post. The initial exception is unrelated to the CryptographicException (or the one Allie got).

The code from the forum post "assume" that any base64 string will create a byte array that is a valid UTF8 string - and that's simply wrong. IOW a base64 string can create a byte array with _any_ content (no restriction) and UTF8 does _not_ accept everything as being a valid string (there are restrictions). 

Now this will work in many cases (a lot of byte[] will be valid from UTF8 pov) but it _will_ fail when:

* a valid UTF8 string can't created from the data;

* an UTF8 can be created using a "long" encoding but, when encoded back, might use a different (shorter) form of encoding. IOW there's more than lone way to encode some things - and that means that roundtripping this way is not possible.
Comment 5 Sebastien Pouliot 2014-02-07 14:19:23 UTC
As to the crypto sample (comment #2) the input data given to the CryptoStream is 22 bytes - which is not a valid block size (AES uses 16 bytes blocks).

The selected padding mode (Zeros) _requires_ the blocks to be padded with 0 (before encryption). What the sample does is *de*crypting data of the wrong length - IOW something (or code) went wrong at encryption time (likely because of an non-roundtripping base64/UTF8 conversion).

I had PJ confirm this is failing on Windows too (since CryptoStream has some, undocumented "features" and other weird behaviour we try to emulate) and the same code fails with a CryptographicException.