DESCryptoServiceProvider and overriding to sbytes

K

kerberos

Hello,

I'm working on porting some Java code to C# and I've run into a
glitch. I have a Java function that does a lot of bit shifting and
builds a byte[] array with values like the following:

10 42 106 -22
18 18 18 -110
18 50 114 114
2 34 34 34
... etc ..

(Apparently Java considers all bytes to be signed.)

Unfortunately, with C# and DESCryptoServiceProvider, everything is a
byte[] and I need to have sbyte[] instead. Merely recasting obviously
doesn't fix issues with CryptoStream(...) and friends. Since I need
to encrypt a key that includes signed bytes, this obviously creates a
problem because the bytes that need to be signed are converted to
unsigned in C#. This causes my keys to not match what was created in
Java.

What would you recommend to make this go in C#? Should I be
overriding DESCryptoServiceProvider or is there another solution?
 
A

Arne Vajhøj

kerberos said:
I'm working on porting some Java code to C# and I've run into a
glitch. I have a Java function that does a lot of bit shifting and
builds a byte[] array with values like the following:

10 42 106 -22
18 18 18 -110
18 50 114 114
2 34 34 34
... etc ..

(Apparently Java considers all bytes to be signed.)

Yes. Big design flaw in Java.
Unfortunately, with C# and DESCryptoServiceProvider, everything is a
byte[] and I need to have sbyte[] instead. Merely recasting obviously
doesn't fix issues with CryptoStream(...) and friends. Since I need
to encrypt a key that includes signed bytes, this obviously creates a
problem because the bytes that need to be signed are converted to
unsigned in C#. This causes my keys to not match what was created in
Java.

What would you recommend to make this go in C#? Should I be
overriding DESCryptoServiceProvider or is there another solution?

You can convert between byte[] and sbyte[] by casting each element.

But most likely you should be able to get the data directly
into byte[] when you read the data.

Arne
 
K

kerberos

Thanks for your reply!

Yes. Big design flaw in Java.
[snip]

Apparently so. :)
You can convert between byte[] and sbyte[] by casting each element.

But most likely you should be able to get the data directly
into byte[] when you read the data.

Hmm, can you clarify this comment in the context of
DESCryptoServiceProvider?
 
A

Arne Vajhøj

kerberos said:
Thanks for your reply!
You can convert between byte[] and sbyte[] by casting each element.

But most likely you should be able to get the data directly
into byte[] when you read the data.

Hmm, can you clarify this comment in the context of
DESCryptoServiceProvider?

Not really, because DESCryptoServiceProvider is not enough
to provide a real context.

Arne
 
K

kerberos

kerberos said:
Thanks for your reply!
You can convert between byte[] and sbyte[] by casting each element.
But most likely you should be able to get the data directly
into byte[] when you read the data.
Hmm, can you clarify this comment in the context of
DESCryptoServiceProvider?

Not really, because DESCryptoServiceProvider is not enough
to provide a real context.

Okay. Here's some code, albeit rough and stripped from my entire app.

protected byte[] someFunc(byte[] myArray) {
byte temp1 = 0;
byte t2 = 0;

for ( int i = 4; i < 8; i++ )
{
t2 = ( byte ) ( ( 1 << ( 7 - i ) ) & 0xff );
src |= (sbyte)((blockValue1[jj] & t2) << (2 * kk - 7));
System.Console.WriteLine("f " + (byte)src);
t2 = 0;
}
}

Now, given the below, how would sbyte[] work here?

protected byte[] makeSum(byte[] mydata, byte[] kb)
{
try
{
sbyte[] skeybytes = new sbyte[keybytes.Length];
for(int i = 0; i < keybytes.Length; i++) {
skeybytes = ((sbyte)keybytes);
}

DESCryptoServiceProvider DES = new
DESCryptoServiceProvider();
DES.Mode = CipherMode.CBC;
DES.Padding = PaddingMode.None;
DES.Key = kb;
DES.IV = kb;

MemoryStream ms = new MemoryStream();

// This is where I might expect to convert sbyte to byte if at all.
CryptoStream cs = new CryptoStream(ms,
DES.CreateEncryptor(DES.Key, DES.IV), CryptoStreamMode.Write);
cs.Write(data, 0, data.Length);
cs.Close();
byte[] encryptedData = ms.ToArray();

byte[] checkSum = new byte[8];
Array.Copy(mydata, mydata.Length - 8, checkSum, 0, 8);

Array.Reverse(checkSum);
return checkSum;
}
catch (Exception e)
{
return null;
}
}
 
A

Arne Vajhøj

kerberos said:
kerberos said:
Thanks for your reply!
You can convert between byte[] and sbyte[] by casting each element.
But most likely you should be able to get the data directly
into byte[] when you read the data.
Hmm, can you clarify this comment in the context of
DESCryptoServiceProvider?
Not really, because DESCryptoServiceProvider is not enough
to provide a real context.

Okay. Here's some code, albeit rough and stripped from my entire app.

protected byte[] someFunc(byte[] myArray) {
byte temp1 = 0;
byte t2 = 0;

for ( int i = 4; i < 8; i++ )
{
t2 = ( byte ) ( ( 1 << ( 7 - i ) ) & 0xff );
src |= (sbyte)((blockValue1[jj] & t2) << (2 * kk - 7));
System.Console.WriteLine("f " + (byte)src);
t2 = 0;
}
}

I do not know what this method is supposed to do.
Now, given the below, how would sbyte[] work here?

protected byte[] makeSum(byte[] mydata, byte[] kb)
{
try
{
sbyte[] skeybytes = new sbyte[keybytes.Length];
for(int i = 0; i < keybytes.Length; i++) {
skeybytes = ((sbyte)keybytes);
}

DESCryptoServiceProvider DES = new
DESCryptoServiceProvider();
DES.Mode = CipherMode.CBC;
DES.Padding = PaddingMode.None;
DES.Key = kb;
DES.IV = kb;

MemoryStream ms = new MemoryStream();

// This is where I might expect to convert sbyte to byte if at all.


Convert what?

The only sbyte[] I can see is skeybytes that already has as a byte[]
in keybytes.
CryptoStream cs = new CryptoStream(ms,
DES.CreateEncryptor(DES.Key, DES.IV), CryptoStreamMode.Write);
cs.Write(data, 0, data.Length);
cs.Close();
byte[] encryptedData = ms.ToArray();

byte[] checkSum = new byte[8];
Array.Copy(mydata, mydata.Length - 8, checkSum, 0, 8);

Array.Reverse(checkSum);
return checkSum;
}
catch (Exception e)
{
return null;
}
}

Arne
 
K

kerberos

Thanks for your response!

Unfortunately, with C# and DESCryptoServiceProvider, everything is a
byte[] and I need to have sbyte[] instead.  Merely recasting obviously
doesn't fix issues with CryptoStream(...) and friends.

Why not?  What errors do you get if you "merely recast"?

In the case of CryptoStream.WriteByte(...) the compiler won't let me
do an implicit (or explicit) conversion:

cs.WriteByte((sbyte)someByte); // Definitely won't compile.

Same goes for DESCryptoServiceProvider.Key and
DESCryptoServiceProvider.IV.
A signed Java byte represents a bit pattern: -1 -> 0xFF.  When you
input signed byte data put it through a filter that changes every
negative byte into the equivalent unsigned bit pattern:

  -1 -> 0xFF -> 255

Something on the lines of:

  byte Convert(sbyte sb) {
    return (sb < 0) ? 256 + sb : sb;
  }

I've looked at this a few times but isn't this ambiguous? It appears
that my results are the same whether I used a filter function or not.
Here's what I'm seeing now:

private byte byteFilter(sbyte sb)
{
return (byte)((sb < 0) ? 256 + sb : sb);
}

protected byte[] doFold(byte[] pbArray)
{
byte[] myKey = new byte[8];
int div = pbArray.Length / 8;

for ( int ii = 0; ii < div; ii++ )
{
byte[] bv1 = new byte[8];
Array.Copy(pbArray, ii * 8, bv1, 0, 8);

if ( ii % 2 == 1 )
{
byte tb1 = 0;
byte tb2 = 0;
byte[] bv2 = new byte[8];

byte ttemplate1 = 0;
sbyte stb1 = 0;

for ( int jj = 0; jj < 8; jj++ )
{
tb2 = 0;

for ( int kk = 4; kk < 8; kk++ )
{
tb2 = (byte) ( ( 1 << ( 7 - kk ) ) &
0xff );
tb1 |= (byte)((bv1[jj] & tb2) << (2 * kk
- 7));
ttb1 |= byteFilter((sbyte)((byte)((bv1
[jj] & tb2) << (2 * kk - 7))));
stb1 |= (sbyte)tb1;
tb2 = 0;
}

// See what I mean?
System.Console.WriteLine("see what i mean? " +
tb1 + "|" + ttb1 + "|" + stb1);
bv2[7 - jj] = tb1;
tb1 = 0;
stb1 = 0;
ttb1 = 0;
}

// ... etc ...

Array.Copy(bv2, 0, bv1, 0, bv2.Length);
}

return myKey;
}

Since results seem to be the same with a filter function or not, this
means I'm still getting incorrect results. :-(
 
K

kerberos

I do not think that your problem is with the filter function, when I
tested it I found that it worked fine - the hex patterns were
unchanged.  Actually I found that a simple byte by byte cast worked
equally well and was simpler.

Ok, and thank you for testing.
I suspect that your problem is elsewhere in your code.  You might want
to try comparing the hex contents of the byte arrrays at different
stages of your code to see where the differences are being introduced.

I ran through a side-by-side comparison of returns (byte[]) for all
functions in my C# and Java code and as you suggested the problem
didn't turn out to be with the hex contents of the byte arrays --
until I reached my hashing function.

<crow taste="delicious">The problem was in my hashing function as I
was hashing (the value of) a variable I hadn't intended. I fixed this
and with the addition I'll note below, my app is working now.</crow>

In my original posting I'd wondered if anybody had a way to override
the behavior of writes to DESCryptoServiceProvider w/CryptoStream. As
it turns out, this too was unnecessary. I ended up attaching a
BinaryWriter to CryptoStream and casted byte to sbyte before doing
bw.Write(sbyte). That worked nicely.
 
D

dan rocks

Can you please let me know if you were able to port the DES Java code to c#? If, yes can you please let me know how you did it .. I am having issues figuring out how to fill the DESCryptoServiceProvider IV fields and also the coversion of java byte to C#sbyte.

Thanks,
Dan



kerberos wrote:

DESCryptoServiceProvider and overriding to sbytes
24-Jul-09

Hello

I'm working on porting some Java code to C# and I've run into
glitch. I have a Java function that does a lot of bit shifting an
builds a byte[] array with values like the following

10 42 106 -2
18 18 18 -11
18 50 114 11
2 34 34 3
... etc .

(Apparently Java considers all bytes to be signed.

Unfortunately, with C# and DESCryptoServiceProvider, everything is
byte[] and I need to have sbyte[] instead. Merely recasting obviousl
doesn't fix issues with CryptoStream(...) and friends. Since I nee
to encrypt a key that includes signed bytes, this obviously creates
problem because the bytes that need to be signed are converted t
unsigned in C#. This causes my keys to not match what was created i
Java

What would you recommend to make this go in C#? Should I b
overriding DESCryptoServiceProvider or is there another solution?

EggHeadCafe - Software Developer Portal of Choice
WPF DataGrid Custom Paging and Sorting
http://www.eggheadcafe.com/tutorial...f-32b2d802ae17/wpf-datagrid-custom-pagin.aspx
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top