.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.
to obtain encrypted string encrypted byte[], should use:
convert.tobase64string(byte[] bytes)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
Post a Comment