Bad Data with Cryptography.RC2 - encryption

There is a special working progress where we encrypt and decrypt an input.
Suddenly, yesterday, there was an encrypted string we weren't able to decrypt.
It seems my cryptographic knowledge aren't good enough to solve this problem.
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Crypto
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Text;
public static class Crypto
{
public static void Main()
{
//String NotWorking_dec = "鈦ꧪ㧘聯ꢮ玗硴廜᭮⸂濅�";
String enc ="mIAU::__*?";
//String dec = "砿첩뜞ꦽ嶾蝡泛ɝࠪ塤偏ꍨ";
Console.WriteLine(decrypt(dec));
//writeFile(encrypt(enc));
Console.ReadLine();
}
private static string key = "ZlKMpRwoPLmNXEpCLxEa6g==";
private static string iv = "U5ZB4W4bQqg=";
private static ICryptoTransform enc;
private static ICryptoTransform dec;
static Crypto()
{
RC2 rc = System.Security.Cryptography.RC2.Create();
enc = rc.CreateEncryptor(Convert.FromBase64String(key), Convert.FromBase64String(iv));
dec = rc.CreateDecryptor(Convert.FromBase64String(key), Convert.FromBase64String(iv));
}
public static String encrypt(String value)
{
byte[] input = toBytes(value);
return toString(enc.TransformFinalBlock(input, 0, input.Length));
}
public static String decrypt(String value)
{
byte[] input = toBytes(value);
Console.WriteLine(input.Length);
return toString(dec.TransformFinalBlock(input, 0, input.Length));
}
private static void writeFile(String value)
{
try
{
StreamWriter sw = new StreamWriter("output.tmp", true);
sw.WriteLine(value);
sw.Close();
}
catch (Exception ex) { }
}
private static byte[] toBytes(String value)
{
return Encoding.Unicode.GetBytes(value);
}
private static String toString(byte[] value)
{
return Encoding.Unicode.GetString(value);
}
}
}
This working progress works for months.
You are able to test it with the input
mIAU::__*?
you get
砿첩뜞ꦽ嶾蝡泛ɝࠪ塤偏ꍨ
decrypt it and you get again
mIAU::__*?
But the encrypted String "鈦ꧪ㧘聯ꢮ玗硴廜᭮⸂濅�" throws errors: (Of course we used the same key and iv)
BAD DATA
bei System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr)
bei System.Security.Cryptography.Utils._DecryptData(SafeKeyHandle hKey, Byte[] data, Int32 ib, Int32 cb, Byte[]& outputBuffer, Int32 outputOffset, PaddingMode PaddingMode, Boolean fDone)
bei System.Security.Cryptography.CryptoAPITransform.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)
bei Crypto.Crypto.decrypt(String value) in c:\Users\Td\Documents\Visual Studio 2013\Projects\Crypto\Crypto\Program.cs:Zeile 56.
bei Crypto.Crypto.Main() in c:\Users\Td\Documents\Visual Studio 2013\Projects\Crypto\Crypto\Program.cs:Zeile 23.
bei System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
bei System.AppDomain.nExecuteAssembly(RuntimeAssembly assembly, String[] args)
bei System.Runtime.Hosting.ManifestRunner.Run(Boolean checkAptModel)
bei System.Runtime.Hosting.ManifestRunner.ExecuteAsAssembly()
bei System.Runtime.Hosting.ApplicationActivator.CreateInstance(ActivationContext activationContext, String[] activationCustomData)
bei System.Runtime.Hosting.ApplicationActivator.CreateInstance(ActivationContext activationContext)
bei System.Activator.CreateInstance(ActivationContext activationContext)
bei Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssemblyDebugInZone()
bei System.Threading.ThreadHelper.ThreadStart_Context(Object state)
bei System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
bei System.Threading.ThreadHelper.ThreadStart()

You cannot simply convert random bytes to strings and back. Not all bytes are valid character encodings. You need to apply for instance base 64 encoding to your binary ciphertext if you require text. Otherwise you will loose data, depending on the value of the ciphertext. And the ciphertext will contain random byte values. So it may fail now and then, as you are currently experiencing.
Java silently converts unknown bytes to characters by default, for instance it will create a � character if it cannot convert byte(s) to a character. This is why this particular string fails.
Besides that, Unicode contains a lot of characters that are not easily printable, and even characters that can be created using either two Unicode code points or a single one. So a Unicode string may have multiple possible encodings, so it is doubly unsuitable for conveying binary data.
All in all, text should not be directly used to convey binary data. The data needs to be encoded first.

Related

Microsoft.SqlServer.Types.SqlGeography Deserialize Error

Our production application recently started getting the elusive "There is an error in XML document (1, 6110)." Up until a few days ago everything was working as expected. I don't have access to the server logs to see if any unexpected updates were performed, but I can't think of a reason why it has been working fine and now doesn't. Just for reference, this is happening on load of a Data set from a web service. The culprit column datatype is Geography and I can confirm the correct version of Microsoft.SqlServer.Types is present on Client and Server sides. "is not allowed here." is what I can't figure out?!?!
Below is the complete error message:
System.InvalidOperationException was caught
HResult=-2146233079
Message=There is an error in XML document (1, 6110).
Source=System.Xml
StackTrace:
at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, Boolean asyncCall)
at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)
at DataFutures.DatabaseRoutines.DFIWebTier.DFIWebTier.Web_ReturnLoadedDataSet(String TableName_String, Boolean UseStoredProcedure_Boolean, String SQLCommandOrStoredProcedureName_String, String ParameterName_String, String SelectValue_String, String ParameterName2_String, String SelectValue2_String, SQLParameter_Class[] SQLParameter_SQLParameter_Class, String ConnectionString_String, String Database_String) in C:\DevApps\TeamServer\Generic Routines\DLLs\DatabaseRoutines\Web References\DFIWebTier\Reference.vb:line 240
at DataFutures.DatabaseRoutines.DF_DataBaseClass.Database_Return_LoadedDataSet(String DataTable_String, Boolean UseStoredProcedure_Boolean, String SQLCommandOrStoredProcedureName_String, String ParameterName_String, String SelectValue_String, String ParameterName2_String, String SelectValue2_String, String ConnectionString_String, SqlTransaction SQL_SqlTransaction, List`1 SQLParameter_SQLParameter_Class, String Database_String) in C:\DevApps\TeamServer\Generic Routines\DLLs\DatabaseRoutines\Classes\DF_DatabaseClass.vb:line 1442
at DataFutures.DatabaseRoutines.DF_DataBaseClass.get_ExecuteReturnLoadedDataSet() in C:\DevApps\TeamServer\Generic Routines\DLLs\DatabaseRoutines\Classes\DF_DatabaseClass.vb:line 736
at DataFutures.Maintenance_Health.FacilityIC_Form.LoadTabPage_GeneralTab() in C:\DevApps\TeamServer\CareScope\Modules\Maintenance\Facility\FacilityIC_Form.vb:line 3905
InnerException: System.InvalidOperationException
HResult=-2146233079
Message=Type 'Microsoft.SqlServer.Types.SqlGeography, Microsoft.SqlServer.Types, Version=12.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91' is not allowed here. See https://go.microsoft.com/fwlink/?linkid=2132227 for more information.
Source=System.Data
StackTrace:
at System.Data.TypeLimiter.EnsureTypeIsAllowed(Type type, TypeLimiter capturedLimiter)
at System.Data.DataColumn.UpdateColumnType(Type type, StorageType typeCode)
at System.Data.DataColumn.set_DataType(Type value)
at System.Data.XSDSchema.SetProperties(Object instance, XmlAttribute[] attrs)
at System.Data.XSDSchema.HandleElementColumn(XmlSchemaElement elem, DataTable table, Boolean isBase)
at System.Data.XSDSchema.HandleParticle(XmlSchemaParticle pt, DataTable table, ArrayList tableChildren, Boolean isBase)
at System.Data.XSDSchema.HandleComplexType(XmlSchemaComplexType ct, DataTable table, ArrayList tableChildren, Boolean isNillable)
at System.Data.XSDSchema.InstantiateTable(XmlSchemaElement node, XmlSchemaComplexType typeNode, Boolean isRef)
at System.Data.XSDSchema.HandleTable(XmlSchemaElement node)
at System.Data.XSDSchema.HandleDataSet(XmlSchemaElement node, Boolean isNewDataSet)
at System.Data.XSDSchema.LoadSchema(XmlSchemaSet schemaSet, DataSet ds)
at System.Data.DataSet.ReadXSDSchema(XmlReader reader, Boolean denyResolving)
at System.Data.DataSet.ReadXml(XmlReader reader, XmlReadMode mode, Boolean denyResolving)
at System.Data.DataSet.ReadXmlSerializable(XmlReader reader)
at System.Data.DataSet.System.Xml.Serialization.IXmlSerializable.ReadXml(XmlReader reader)
at System.Xml.Serialization.XmlSerializationReader.ReadSerializable(IXmlSerializable serializable, Boolean wrappedAny)
at System.Xml.Serialization.XmlSerializationReader.ReadSerializable(IXmlSerializable serializable)
at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderDFIWebTier.Read6_Item()
at Microsoft.Xml.Serialization.GeneratedAssembly.ArrayOfObjectSerializer7.Deserialize(XmlSerializationReader reader)
at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
InnerException:
The reason is right there in the link. You have to opt-in for serializing types other than the basic ones. You probably have this configured for a previous version of the Spatial types, but when they were updated on the server, the configuration didn't get updated on the client.
Here's an example:
using System.Data.SqlClient;
using Microsoft.SqlServer.Types;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Threading;
using System.Threading.Tasks;
namespace SqlClientTest
{
class Program
{
static void Main(string[] args)
{
var constr = "server=localhost;database=master;integrated security=true;";
using (var con = new SqlConnection(constr))
{
con.Open();
Type[] extraAllowedTypes = new Type[]
{
typeof(SqlGeography)
};
AppDomain.CurrentDomain.SetData("System.Data.DataSetDefaultAllowedTypes", extraAllowedTypes);
var sel = new SqlCommand("select geography::STGeomFromText('LINESTRING(-122.360 47.656, -122.343 47.656 )', 4326) shape", con);
var da = new SqlDataAdapter(sel);
var ds = new DataSet();
da.Fill(ds);
var ms = new MemoryStream();
ds.WriteXml(ms, XmlWriteMode.WriteSchema);
ms.Position = 0;
using (var f = File.OpenWrite("out.xml"))
{
ms.CopyTo(f);
}
ms.Position = 0;
var ds2 = new DataSet();
ds2.ReadXml(ms);
}
}
}
}

No parameterless constructor defined for type

I am trying to learn and to do something with asp.net. I'm trying to get some info from json api using import.io's api, but i could not figure out something. I am trying to solve it till 2 days:
ERROR : No parameterless constructor defined for type of 'imdb_io_web.IMDB[]'
Why am I getting that error I really don't understand?
I have a class
namespace imdb_io_web
{
public class IMDB
{
public string director { get; set; }
}
}
and trying to get director name from IMDB
var wc = new WebClient();
var serializer = new JavaScriptSerializer();
var result = serializer.Deserialize<IMDB[]>(wc.DownloadString("MYAPI"));
foreach (var item in result) { Label1.Text = item.director; }
[MissingMethodException: No parameterless constructor defined for type of 'imdb_io_web.IMDB[]'.]
System.Web.Script.Serialization.ObjectConverter.ConvertDictionaryToObject(IDictionary`2 dictionary, Type type, JavaScriptSerializer serializer, Boolean throwOnError, Object& convertedObject) +527729
System.Web.Script.Serialization.ObjectConverter.ConvertObjectToTypeInternal(Object o, Type type, JavaScriptSerializer serializer, Boolean throwOnError, Object& convertedObject) +66
System.Web.Script.Serialization.ObjectConverter.ConvertObjectToTypeMain(Object o, Type type, JavaScriptSerializer serializer, Boolean throwOnError, Object& convertedObject) +145
System.Web.Script.Serialization.JavaScriptSerializer.Deserialize(JavaScriptSerializer serializer, String input, Type type, Int32 depthLimit) +66
System.Web.Script.Serialization.JavaScriptSerializer.Deserialize(String input) +70
imdb_io_web.WebForm1.Page_Load(Object sender, EventArgs e) in C:\Users\ahmetozsari\documents\visual studio 2010\Projects\imdb_io_web\imdb_io_web\WebForm1.aspx.cs:26
System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +51
System.Web.UI.Control.OnLoad(EventArgs e) +92
System.Web.UI.Control.LoadRecursive() +54
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +772
Either you deserialize a single element:
var result = serializer.Deserialize<IMDB>(wc.DownloadString("MYAPI"));
Label1.Text = item.director;
or a list
var result = serializer.Deserialize<List<IMDB>>(wc.DownloadString("MYAPI"));
foreach (var item in result) { Label1.Text = item.director; }
The array type (IMDB[]), as you read in the exception, cannot be used as a type parameter for the deserializer as it lacks the parameterless constructor. Using List<IMDB> should possibly resolve the issue.
Firstly you can use HttpClient class for API operations.
using (var httpClient = new HttpClient())
{
var operationResult = await httpClient.GetStringAsync(#"http://localhost/api/requests");
}
Secondly, for JSON conversion operations you can use Json.NET
using Newtonsoft.Json;
public class RequestJson
{
[JsonProperty("request")]
public Request Request { get; set; }
}
public class Request
{
[JsonProperty("name")]
public string Name{ get; set; }
}
JsonConvert.DeserializeObject<List<RequestJson>>(operationResult );
You have to use List template type because with my understanding when you are creating an array type then Newtonsoft.Json would not be able to instantiate the object because it needs a size.

WCF un-expected end of file error

Recently I have upgraded my project from .NET Framework 3.5 to 4.0. For WCF I am using custom basic authentication.
Before conversion, all was working fine. However, after conversion I am getting "Unexpected end of file error". The stack strace is as below :
at System.Xml.EncodingStreamWrapper.ProcessBuffer(Byte[] buffer, Int32 offset, Int32 count, Encoding encoding)
at System.Xml.XmlUTF8TextReader.SetInput(Byte[] buffer, Int32 offset, Int32 count, Encoding encoding, XmlDictionaryReaderQuotas quotas, OnXmlDictionaryReaderClose onClose)
at System.Xml.XmlDictionaryReader.CreateTextReader(Byte[] buffer, Int32 offset, Int32 count, Encoding encoding, XmlDictionaryReaderQuotas quotas, OnXmlDictionaryReaderClose onClose)
at System.ServiceModel.Channels.TextMessageEncoderFactory.TextMessageEncoder.WriteMessage(Message message, Int32 maxMessageSize, BufferManager bufferManager, Int32 messageOffset)
at System.ServiceModel.Channels.WebMessageEncoderFactory.WebMessageEncoder.WriteMessage(Message message, Int32 maxMessageSize, BufferManager bufferManager, Int32 messageOffset)
at System.ServiceModel.Channels.HttpOutput.SerializeBufferedMessage(Message message)
at System.ServiceModel.Channels.HttpOutput.Send(TimeSpan timeout)
at System.ServiceModel.Channels.HttpPipeline.EmptyHttpPipeline.SendReplyCore(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.HttpPipeline.EmptyHttpPipeline.SendReply(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.HttpRequestContext.OnReply(Message message, TimeSpan timeout)
at System.ServiceModel.Activation.HostedHttpContext.OnReply(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.RequestContextBase.Reply(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.RequestContextBase.Reply(Message message)
at ihv1Role.auth.BasicAuthenticationInterceptor.ProcessRequest(RequestContext& requestContext) in d:\src\auth\BasicAuthenticationInterceptor.cs:line 78
The class and method in which I am getting error are as below :
p
ublic class BasicAuthenticationInterceptor : RequestInterceptor
{
MembershipProvider provider;
string realm;
public BasicAuthenticationInterceptor(MembershipProvider provider, string realm)
: base(false)
{
this.provider = provider;
this.realm = realm;
}
protected string Realm
{
get { return realm; }
}
protected MembershipProvider Provider
{
get { return provider; }
}
public override void ProcessRequest(ref RequestContext requestContext)
{
HttpRequestMessageProperty request = (HttpRequestMessageProperty)requestContext.RequestMessage.Properties[HttpRequestMessageProperty.Name];
string[] credentials = ExtractCredentials(requestContext.RequestMessage);
if (credentials.Length > 0 && AuthenticateUser(credentials[0], credentials[1], IsTestMode))
{
InitializeSecurityContext(requestContext.RequestMessage, credentials[0]);
}
else
{
Message reply = Message.CreateMessage(MessageVersion.None, null);
HttpResponseMessageProperty responseProperty = new HttpResponseMessageProperty() { StatusCode = HttpStatusCode.Unauthorized };
responseProperty.Headers.Add("WWW-Authenticate",
String.Format("Basic realm=\"{0}\"", Realm));
reply.Properties[HttpResponseMessageProperty.Name] = responseProperty;
requestContext.Reply(reply); // **Here I am getting error**
requestContext = null;
}
}
}
If the username and password in header are valid then whole service runs well. I am getting this error only if request is not authenticated.
Any solution?
Thanks
Resolved it my self :
I had added tag twice in Web.config.
Removed it and now my service is working fine.

"Invalid use of response filter" when rewriting ASP.NET output

I have a very basic ASP.NET response filter that works "fine." I use it to replace the domain for static resources.
My code in the controller looks like this:
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
_cdnRewriter.Stream = filterContext.RequestContext.HttpContext.Response.Filter;
filterContext.RequestContext.HttpContext.Response.Filter = _cdnRewriter;
}
And the rewrite filter itself:
public override void Write(byte[] buffer, int offset, int count)
{
var html = Encoding.Default.GetString(buffer, offset, count);
//manipulate html
byte[] outData = Encoding.Default.GetBytes(html);
Stream.Write(outData, 0, outData.GetLength(0));
}
For certain pages on my site (I can't find the rhyme or reason yet), I get a "HTTP Web Exception: Invalid use of response filter" perhaps 90% of the time. Simply refreshing a dozen times will get the correct output, but refreshing again will show the exception:
[HttpException (0x80004005): Invalid use of response filter]
System.Web.HttpResponseStreamFilterSink.VerifyState() +4097234
System.Web.HttpResponseStreamFilterSink.Write(Byte[] buffer, Int32 offset, Int32 count) +28
NeoSmart.Web.CdnRewriteFilter.Write(Byte[] buffer, Int32 offset, Int32 count) +452
System.Web.HttpWriter.FilterIntegrated(Boolean finalFiltering, IIS7WorkerRequest wr) +359
System.Web.HttpResponse.FilterOutput() +121
System.Web.CallFilterExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +119
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +165
Am I doing something wrong in my response filter?
I probably should have known better: response filters should not be shared. I was using an object per class, creating a new response filter each time the OnActionExecuted function was called resolved the issue.

ASP.NET RSACryptoServiceProvider throws Invalid flags specified exception

I got problem when try to generate keys using ASP.NET (.NET 4) for RSA, the RSACryptoServiceProvider throws invalid flags specified exception.
[CryptographicException: Invalid flags specified.
]
System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr) +33
System.Security.Cryptography.Utils._GenerateKey(SafeProvHandle hProv, Int32 algid, CspProviderFlags flags, Int32 keySize, SafeKeyHandle& hKey) +0
System.Security.Cryptography.Utils.GetKeyPairHelper(CspAlgorithmType keyType, CspParameters parameters, Boolean randomKeyContainer, Int32 dwKeySize, SafeProvHandle& safeProvHandle, SafeKeyHandle& safeKeyHandle) +9719339
System.Security.Cryptography.RSACryptoServiceProvider.GetKeyPair() +89
System.Security.Cryptography.RSACryptoServiceProvider.ExportParameters(Boolean includePrivateParameters) +38
System.Security.Cryptography.RSA.ToXmlString(Boolean includePrivateParameters) +45
I initialize the RSA using this code:
var _cpsParameter = new CspParameters();
_cpsParameter.Flags = CspProviderFlags.UseMachineKeyStore;
var rsaProvider = new RSACryptoServiceProvider(bitStrength, _cpsParameter);
string publicAndPrivateKeys = rsaProvider.ToXmlString(true);
string justPublicKey = rsaProvider.ToXmlString(false);
Any idea how to solve this ?
One possible explanation might be that you already have a non-exportable key in the key-container with the name "" (in that case .NET will just use the existing key instead of overwriting it with a new key).
Try this code instead and see if that makes a difference:
var cspParameters = new CspParameters();
cspParameters.Flags = CspProviderFlags.UseMachineKeyStore;
cspParameters.KeyContainerName = Guid.NewGuid().ToString();
var rsaProvider = new RSACryptoServiceProvider(bitStrength, cspParameters);
string publicAndPrivateKeys = rsaProvider.ToXmlString(true);
string justPublicKey = rsaProvider.ToXmlString(false);

Resources