.net - Occasional Bad Data Error while decrypting the string : System.Security.Cryptography.CryptographicException -


in asp.net webforms app (the app running on windows server 2008 r2, iis 7.5 , runtime v4.0 integrated mode app pool if matters), encrypting data, putting on querystring , decrypting data using system.security.cryptography.symmetricalgorithm class. having problems decrypting data getting following exception;

bad data.

description: unhandled exception occurred during execution of current web request. please review stack trace more information error , originated in code.

exception details: system.security.cryptography.cryptographicexception: bad data.

source error:

an unhandled exception generated during execution of current web request. information regarding origin , location of exception can identified using exception stack trace below.

stack trace:

[cryptographicexception: bad data. ]
system.security.cryptography.cryptographicexception.throwcryptographicexception(int32 hr) +33
system.security.cryptography.utils._decryptdata(safekeyhandle hkey, byte[] data, int32 ib, int32 cb, byte[]& outputbuffer, int32 outputoffset, paddingmode paddingmode, boolean fdone) +0
system.security.cryptography.cryptoapitransform.transformfinalblock(byte[] inputbuffer, int32 inputoffset, int32 inputcount) +313
system.security.cryptography.cryptostream.flushfinalblock() +33 cryptography35.symmetricencryptionutility.decryptdata(byte[] data, string keyfile) in e:\documents\@library\cryptography35\cryptography35\symmetricencryptionutility.cs:124 cryptography35.symmetricquerystring.symmetriclyencryptedquerystring..ctor(string encrypteddata, string keyfilename, string algorithmname) in e:\documents\@library\cryptography35\cryptography35\symmetricquerystring\symmetriclyencryptedquerystring.cs:67 webforms.web.views.purchase_a.getsymmetriclyencryptedquerystring() in e:\documents\webforms.web\views\purchase-a.aspx.cs:35 webforms.web.views.purchase_a.page_load(object sender, eventargs e) in e:\documents\webforms.web\views\purchase-a.aspx.cs:56 system.web.util.callihelper.eventargfunctioncaller(intptr fp, object o, object t, eventargs e) +14 system.web.util.callieventhandlerdelegateproxy.callback(object sender, eventargs e) +35
system.web.ui.control.onload(eventargs e) +91
system.web.ui.control.loadrecursive() +74 system.web.ui.page.processrequestmain(boolean includestagesbeforeasyncpoint, boolean includestagesafterasyncpoint) +2207 version information: microsoft .net framework version:4.0.30319; asp.net version:4.0.30319.1

as indicated, getting error on occasion, not every time run that. don't know doing wrong (on encryption stage or decryption stage) here code used that;

private symmetriclyencryptedquerystring getsymmetriclyencryptedquerystring() {      #region _decrypting value      string keyfilename;     string algorithmname = "des";      cryptography35.symmetricencryptionutility.algorithmname = algorithmname;     keyfilename = httpcontext.current.server.mappath("~/@config/") + "\\symmetric_key.config";      #endregion      #region _reading , assigning value      if (request.querystring["q"] == null)         throw new nullreferenceexception("querystring value null on search result page");      symmetriclyencryptedquerystring querystring = new symmetriclyencryptedquerystring(request.querystring["q"], keyfilename, algorithmname);      #endregion      return querystring; } 

symmetriclyencryptedquerystring class

public class symmetriclyencryptedquerystring : system.collections.specialized.stringdictionary {          public string keyfilename { get; set; }         public string algorithmname { get; set; }          /// <summary>         /// use encrypte value         /// </summary>         /// <param name="keyfilename"></param>         /// <param name="algorithmname"></param>         public symmetriclyencryptedquerystring(string keyfilename, string algorithmname) {              keyfilename = keyfilename;             algorithmname = algorithmname;          }          /// <summary>         /// use decrypte value.         /// </summary>         /// <param name="encrypteddata"></param>         /// <param name="keyfilename"></param>         /// <param name="algorithmname"></param>         public symmetriclyencryptedquerystring(string encrypteddata, string keyfilename, string algorithmname) {              #region _initials              keyfilename = keyfilename;             algorithmname = algorithmname;              if (string.isnullorempty(algorithmname)){                 symmetricencryptionutility.algorithmname = algorithmname;             }             else{                 symmetricencryptionutility.algorithmname = "des";             }              symmetricencryptionutility.protectkey = false;              // check encryption key             if (!file.exists(keyfilename)){                 throw new filenotfoundexception("keyfilename  symmetriclyencryptedquerystring not found on '" + keyfilename + "'!");             }              #endregion              //arrange data             //in order not following exception             //invalid length base-64 char array.             //byte[] rawdata = convert.frombase64string(encrypteddata);             encrypteddata = encrypteddata.replace(" ", "+");             int mod4 = encrypteddata.length % 4;             if (mod4 > 0)                 encrypteddata += new string('=', 4 - mod4);              // decrypt data passed in             byte[] rawdata = convert.frombase64string(encrypteddata);             string decryptedval = symmetricencryptionutility.decryptdata(rawdata, keyfilename);             string stringdata = decryptedval;              // split data , add contents             int index;             string[] splitteddata = stringdata.split(new char[] { '&' });             foreach (string singledata in splitteddata) {                  index = singledata.indexof('=');                 base.add(                     httputility.urldecode(singledata.substring(0, index)),                     httputility.urldecode(singledata.substring(index + 1))                 );              }         }          public override string tostring() {              #region _initials              if (string.isnullorempty(algorithmname)) {                 symmetricencryptionutility.algorithmname = algorithmname;             } else {                 symmetricencryptionutility.algorithmname = "des";             }              symmetricencryptionutility.protectkey = false;              // check encryption key             if (!file.exists(keyfilename)) {                 throw new filenotfoundexception("keyfilename asymmetriclyencryptedquerystring not found on '" + keyfilename + "'!");             }              #endregion              #region _prepare querystring              // go through contents , build              // typical query string             stringbuilder content = new stringbuilder();              foreach (string key in base.keys) {                  content.append(httputility.urlencode(key));                 content.append("=");                 content.append(httputility.urlencode(base[key]));                 content.append("&");              }              // remove last '&'             content.remove(content.length - 1, 1);               #endregion              #region _encrypt contents              // encrypt contents             byte[] data = symmetricencryptionutility.encryptdata(content.tostring(), keyfilename);             string encryptedval = convert.tobase64string(data);              #endregion              return encryptedval;          }      } 

symmetricencryptionutility class

public static class symmetricencryptionutility {      private static bool _protectkey;     private static string _algorithmname;      // shhh!!! don't tell anybody!     private const string mykey = "m$%&kljasldk$%/65asjdl";      public static string algorithmname {          { return _algorithmname; }         set { _algorithmname = value; }     }      public static bool protectkey {          { return _protectkey; }         set { _protectkey = value; }     }      public static void generatekey(string targetfile) {          // create algorithm         symmetricalgorithm algorithm = symmetricalgorithm.create(algorithmname);         algorithm.generatekey();          // no key         byte[] key = algorithm.key;          if (protectkey)         {             // use dpapi encrypt key             key = protecteddata.protect(                 key, null, dataprotectionscope.localmachine);         }          // store key in file called key.config         using (filestream fs = new filestream(targetfile, filemode.create))         {             fs.write(key, 0, key.length);         }     }      public static void readkey(symmetricalgorithm algorithm, string keyfile)     {         byte[] key;          using (filestream fs = new filestream(keyfile, filemode.open))         {             key = new byte[fs.length];             fs.read(key, 0, (int)fs.length);         }          if (protectkey)             algorithm.key = protecteddata.unprotect(key, null, dataprotectionscope.localmachine);         else             algorithm.key = key;     }      public static byte[] encryptdata(string data, string keyfile)     {         // convert string data byte array         byte[] cleardata = encoding.utf8.getbytes(data);          // create algorithm         symmetricalgorithm algorithm = symmetricalgorithm.create(algorithmname);         readkey(algorithm, keyfile);          // encrypt information         memorystream target = new memorystream();          // append iv         algorithm.generateiv();         target.write(algorithm.iv, 0, algorithm.iv.length);          // encrypt actual data         cryptostream cs = new cryptostream(target, algorithm.createencryptor(), cryptostreammode.write);         cs.write(cleardata, 0, cleardata.length);         cs.flushfinalblock();          // output bytes of encrypted array textbox         return target.toarray();     }      public static string decryptdata(byte[] data, string keyfile) {          // create algorithm         symmetricalgorithm algorithm = symmetricalgorithm.create(algorithmname);         readkey(algorithm, keyfile);          // decrypt information         memorystream target = new memorystream();          // read iv         int readpos = 0;         byte[] iv = new byte[algorithm.iv.length];         array.copy(data, iv, iv.length);         algorithm.iv = iv;         readpos += algorithm.iv.length;          cryptostream cs = new cryptostream(target, algorithm.createdecryptor(), cryptostreammode.write);         cs.write(data, readpos, data.length - readpos);         cs.flushfinalblock();          // bytes memory stream , convert them text         return encoding.utf8.getstring(target.toarray());     }  } 

update figured else. on 1 of pages doing following thing;

protected override void oninit(eventargs e) {      string url = request.url.absoluteuri.tolower();     if (url.startswith("http:"))     {         response.redirect(url.replace("http://", "https://"), true);     } } 

i figured causes problem. (remember encrypted data sits inside query string) when try reach page http , redirects https , boom. gives me error. ok found source of error shouldn't happening anyway.

you have bug lurking in code...

you should never use of system.text.encoding classes cipher text. will experience intermittent errors. should use base64 encoding , system.convert class methods.

  1. to obtain encrypted string encrypted byte[], should use: convert.tobase64string(byte[] bytes)

  2. to obtain a raw byte[] string encrypted, should use: convert.frombase64string(string data)

for additional info, please refer ms security guru shawn farkas's post @ http://blogs.msdn.com/b/shawnfa/archive/2005/11/10/491431.aspx


Comments

Popular posts from this blog

c++ - Is it possible to compile a VST on linux? -

c# - SharpSVN - How to get the previous revision? -

php cli reading files and how to fix it? -