Porting code containing unsigned char pointer in C to C #

I have this code in C that I need to connect to C #:

void CryptoBuffer(unsigned char *Buffer, unsigned short length) { unsigned short i; for(i=0; i < length; i++) { *Buffer ^= 0xAA; *Buffer++ += 0xC9; } } 

I tried this:

 public void CryptoBuffer(byte[] buffer, int length) { for(int i = 0; i < length; i++) { buffer[i] ^= 0xAA; buffer[i] += 0xC9; } } 

But the result is not as expected.

According to an example:

 A5 03 18 01... 

should be as follows:

 A5 6F 93 8B... 

He also says that the first byte is not encrypted, which is why the A5 remains the same.

EDIT for clarification . The specification simply says that you should skip the first byte, this is not included in the details, so I assume that you just pass the sequence from position 1 to the last position to skip the first byte.

But my result with this C # port:

 A5 72 7B 74... 

Is this the correct port or am I missing something?

EDIT 2 . For further clarification, this is a closed protocol, so I can not go into details, so I provided enough information to help me transfer the code, that the C-code was the one that was given to me, and that the specification stated that it would do . The real problem was that "0xAA" was wrong in the specification, so the output was not expected. The C # code given here and the accepted answer are correct.

+7
source share
7 answers

Let's break it, we will take one step at a time.

 void CryptoBuffer(unsigned char *Buffer, unsigned short length) { unsigned short i; for(i=0; i < length; i++) { *Buffer ^= 0xAA; *Buffer++ += 0xC9; } } 

Regardless of some other notes, this is how you usually do it in C / C ++. There is nothing unusual in this code, and it is not too difficult, but I think it’s good to break it to show you what is happening.

Notes:

  • unsigned char basically matches byte in C #
  • unsigned length has a value between 0-65536. Int should do the trick.
  • Buffer has post increment
  • Byte assignment (+ = 0xC9) will overflow. If it overflows it, it is truncated to 8 bits in this case.
  • The buffer is passed through ptr, so the pointer in the calling method will remain the same.
  • This is just basic C code, not C ++. It is perfectly safe to assume that people do not use operator overloading here.

The only "hard" thing here is Buffer ++. Details can be found in Sutter's Exceptional C ++ book, but a small example also explains this. And, fortunately, we have a great example at our disposal. literal translation of the above code:

 void CryptoBuffer(unsigned char *Buffer, unsigned short length) { unsigned short i; for(i=0; i < length; i++) { *Buffer ^= 0xAA; unsigned char *tmp = Buffer; *tmp += 0xC9; Buffer = tmp + 1; } } 

In this case, the temporary variable can be solved trivially, which leads to:

 void CryptoBuffer(unsigned char *Buffer, unsigned short length) { unsigned short i; for(i=0; i < length; i++) { *Buffer ^= 0xAA; *Buffer += 0xC9; ++Buffer; } } 

Changing this code to C # is pretty simple right now:

 private void CryptoBuffer(byte[] Buffer, int length) { for (int i=0; i<length; ++i) { Buffer[i] = (byte)((Buffer[i] ^ 0xAA) + 0xC9); } } 

This is basically the same as your ported code. This means that somewhere along the way, something went wrong ... So, let me hack the cryptobuffer, right ?:-)

If we assume that the first byte is not used (as you said) and that β€œ0xAA” and / or β€œ0xC9” are wrong, we can just try all the combinations:

 static void Main(string[] args) { byte[] orig = new byte[] { 0x03, 0x18, 0x01 }; byte[] target = new byte[] { 0x6F, 0x93, 0x8b }; for (int i = 0; i < 256; ++i) { for (int j = 0; j < 256; ++j) { bool okay = true; for (int k = 0; okay && k < 3; ++k) { byte tmp = (byte)((orig[k] ^ i) + j); if (tmp != target[k]) { okay = false; break; } } if (okay) { Console.WriteLine("Solution for i={0} and j={1}", i, j); } } } Console.ReadLine(); } 

There we go: oops no solutions. This means that cryptobuffer is not doing what you think it is doing, or part of the C code is missing here. F.ex. Do they really pass the "Buffer" to the CryptoBuffer method, or do they change the pointer earlier?

In conclusion, I believe that the only good answer is that there is no critical information to address this issue.

+9
source

The example you provided is not compatible with the code in sample C, and the code C and C # gives identical results.

+5
source

Porting looks right; can you explain why 03 should become 6F? The fact that the result seems to be the β€œexpected” value at 03 is a little suspicious to me.

+3
source

The port looks correct.

What I would do in this situation is to take a piece of paper and a pen, write down the bytes in binary format, make XOR, and then add. Now compare this with the C and C # codes.

+1
source

In C #, you are overflowing bytes, so it is truncated to 0x72. Here is the math to convert 0x03 in binary and hexadecimal:

  00000011 0x003 ^ 10101010 0x0AA = 10101001 0x0A9 + 11001001 0x0C9 = 101110010 0x172 
+1
source

With the original method in C, we first assume that the sequence is decrypted / encrypted using a symmetric method with a call to CryptoBuffer

  • Initially call on a5 03 18 01 ...

     a5 03 18 01 ... => d8 72 7b 74 ... 

    then on d8 72 7b 74 ...

     d8 72 7b 74 ... => 3b a1 9a a7 ... 
  • Initially call on a5 6f 93 8b ...

     a5 6f 93 8b ... => d8 8e 02 ea ... 

    then on d8 8e 02 ea ...

     d8 8e 02 ea ... => 3b ed 71 09 ... 

and we know that this is impossible.

Of course, you may have an asymmetric decryption method; but first we need either a5 03 18 01 ... => a5 6f 93 8b ... or the opposite direction will be proved with any possible magic number. The brute force analysis code is placed at the end of the message.

I made a magic variable number for testing. When analyzing reproducibility, we found that the original sequence can be played back every 256 calls on a continuously changing magic number. Well, with what we experienced, it is still possible here.

However, a feasibility study analysis that checks all cases of 256*256=65536 with both directions is from original => expected and expected => original , and no one does it.

And now we know that it is impossible to decrypt the encrypted sequence before the expected result.

Thus, we can only say that the expected behavior of both the language and your code is identical , but for the expected result it is impossible because the assumption was violated,


Code for analysis

 public void CryptoBuffer(byte[] buffer, ushort magicShort) { var magicBytes=BitConverter.GetBytes(magicShort); var count=buffer.Length; for(var i=0; i<count; i++) { buffer[i]^=magicBytes[1]; buffer[i]+=magicBytes[0]; } } int Analyze( Action<byte[], ushort> subject, byte[] expected, byte[] original, ushort? magicShort=default(ushort?) ) { Func<byte[], String> LaHeX= // narrowing bytes to hex statement arg => arg.Select(x => String.Format("{0:x2}\x20", x)).Aggregate(String.Concat); var temporal=(byte[])original.Clone(); var found=0; for(var i=ushort.MaxValue; i>=0; --i) { if(found>255) { Console.WriteLine(": might found more than the number of square root; "); Console.WriteLine(": analyze stopped "); Console.WriteLine(); break; } subject(temporal, magicShort??i); if(expected.SequenceEqual(temporal)) { ++found; Console.WriteLine("i={0:x2}; temporal={1}", i, LaHeX(temporal)); } if(expected!=original) temporal=(byte[])original.Clone(); } return found; } void PerformTest() { var original=new byte[] { 0xa5, 0x03, 0x18, 0x01 }; var expected=new byte[] { 0xa5, 0x6f, 0x93, 0x8b }; Console.WriteLine("--- reproducibility analysis --- "); Console.WriteLine("found: {0}", Analyze(CryptoBuffer, original, original, 0xaac9)); Console.WriteLine(); Console.WriteLine("--- feasibility analysis --- "); Console.WriteLine("found: {0}", Analyze(CryptoBuffer, expected, original)); Console.WriteLine(); // swap original and expected var temporal=original; original=expected; expected=temporal; Console.WriteLine("--- reproducibility analysis --- "); Console.WriteLine("found: {0}", Analyze(CryptoBuffer, original, original, 0xaac9)); Console.WriteLine(); Console.WriteLine("--- feasibility analysis --- "); Console.WriteLine("found: {0}", Analyze(CryptoBuffer, expected, original)); Console.WriteLine(); } 
0
source

Here is a demo

http://codepad.org/UrX0okgu

shows that the source code, taking into account the input A5 03 18 01 produces D8 72 7B 01 ; so

  • the rule that the first byte is not decoded can be correct only if the buffer is sent starting from the 2nd (show us the call)

  • the output does not match (will you miss other calls?)

So, your translation is correct, but your expectations of what the original code does are not.

0
source

All Articles