I have an interesting issue handling 8-bit "ASCII" characters in LINQ-to-Entities and am hoping someone can give me a tip.
I have inherited a SQL Server 2000 database that has some pseudo-encrypted columns where they just XOR'd the string with 0xFF
. Don't know why and I know it's lame but that's where we are now.
These columns are of SQL datatype char(7)
and char(14)
. When you XOR using 0xFF
you get the 8th bit set in every case, so you end up with non-ASCII (by Microsoft's definition anyway) characters. UTF-8 seems to be indicated here but the decoding gets messed up.
I am able to read and decode these strings as follows:
String
.byte[]
using System.Text.Encoding.GetEncoding(1252).GetBytes()
0xFF
System.Text.Encoding.GetEncoding(1252).GetString()
This works perfectly.
The problem I'm having is that I can't seem to put an ENCODED string back to SQL Server using LINQ.
I am basically following the reverse process and am doing:
ASCIIEncoding.GetBytes()
. (No need for CodePage 1252 here as this is a straight string.)0xFF
.GetEncoding(1252).GetString()
.If I look at my string, it's exactly what I'd expect. But if I stuff that in my entity and do a SaveChanges()
the resultant value in SQL Server is always "?????"
of some length.
I'm sure I'm missing something here but I've tried everything I can think of and can't get it. For now I just fell back to the old-fashioned way of using a SqlCommand
and doing an UPDATE with the encoded strings as SqlParameters
. No problem there, works every time.
Thanks in advance for any assistance.
Update:
I tried the suggestion from JamieSee and I'm not even getting good decoding with his method. I have:
static void Main(string[] args)
{
Encoding characterEncoding = Encoding.GetEncoding(28591);
HCBPWEBEntities ent = new HCBPWEBEntities();
var encUser =
(from users in ent.tblEmployer
where users.ipkEmpId == 357
select users.sKey).First();
Console.Out.WriteLine("Original XOR Encoded PW: {0}", encUser.ToString().Trim());
byte[] originalBytes = (from character in characterEncoding.GetBytes(encUser.ToString().Trim())
select (byte)(character)).ToArray();
Console.Write("Original Bytes:\t");
foreach (byte b in originalBytes)
{
Console.Write("{0:x} ", b);
}
Console.WriteLine(String.Empty);
byte[] decodedBytes = (from character in characterEncoding.GetBytes(encUser.ToString().Trim())
select (byte)(character ^ 0xFF)).ToArray();
Console.Write("Decoded Bytes:\t");
foreach (byte b in decodedBytes)
{
Console.Write("{0:x} ", b);
}
Console.WriteLine(String.Empty);
string decoded = characterEncoding.GetString(decodedBytes);
Console.WriteLine("Decoded PW: {0}", decoded);
ent.Dispose();
}
But the result of that are:
Original XOR Encoded PW: z?o> Original Bytes: 7a 9d 6f 3e Decoded Bytes: 85 62 90 c1 Decoded PW: ?b?A
The password is actually "abcd"
LINQ to Entities provides Language-Integrated Query (LINQ) support that enables developers to write queries against the Entity Framework conceptual model using Visual Basic or Visual C#. Queries against the Entity Framework are represented by command tree queries, which execute against the object context.
First off, if you're starting a new project, use Entity Framework ("EF") instead of Linq to SQL because it now generates far better SQL (more like Linq to SQL does) and is easier to maintain ("L2S").
LINQ to SQL allow you to query and modify SQL Server database by using LINQ syntax. Entity framework is a great ORM shipped by Microsoft which allow you to query and modify RDBMS like SQL Server, Oracle, DB2 and MySQL etc. by using LINQ syntax.
Entity Framework (EF) is an object-relational mapper that enables . NET developers to work with relational data using domain-specific objects. It eliminates the need for most of the data-access code that developers usually need to write. Get it: Add this to your project and start taking advantage of this powerful O/RM.
Don't use code page 1252 use Encoding.GetEncoding(28591)
(iso-8859-1) or Encoding.GetEncoding(850)
(ibm850), either of which gives you 8-bit ASCII-based character sets.
Here's some quick & dirty code, which you can try with different encodings, to demonstrate your issue and the solution:
public static void Main()
{
Encoding characterEncoding = Encoding.GetEncoding(28591);
string original = "This is some bogus data to test the problem.";
Console.WriteLine("Original String: {0}", original);
Console.Write("Original Bytes: ");
foreach (byte b in characterEncoding.GetBytes(original))
{
Console.Write("{0:x}", b);
}
Console.WriteLine();
byte[] encodedBytes = (from character in characterEncoding.GetBytes(original)
select (byte)(character ^ 0xFF)).ToArray();
Console.Write("Encoded Bytes: ");
foreach (byte b in encodedBytes)
{
Console.Write("{0:x}", b);
}
Console.WriteLine();
string encoded = characterEncoding.GetString(encodedBytes);
byte[] decodedBytes = (from character in characterEncoding.GetBytes(encoded)
select (byte)(character ^ 0xFF)).ToArray();
Console.Write("Decoded Bytes: ");
foreach (byte b in decodedBytes)
{
Console.Write("{0:x}", b);
}
Console.WriteLine();
string decoded = characterEncoding.GetString(decodedBytes);
Console.WriteLine("Decoded String: {0}", decoded);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With