I'm attempting to generate a valid PPP Frame Check Sequence (FCS) using C#. The code I have implemented is based off of this answer.
public static class Crc16
{
const ushort polynomial = 0x8408;
static readonly ushort[] fcstab = new ushort[256];
// This is the fcstab from RFC1662
// https://www.rfc-editor.org/rfc/rfc1662#ref-7
//static readonly ushort[] fcstab = new ushort[] {
// 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
// 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
// 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
// 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
// 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
// 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
// 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
// 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
// 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
// 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
// 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
// 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
// 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
// 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
// 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
// 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
// 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
// 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
// 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
// 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
// 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
// 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
// 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
// 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
// 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
// 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
// 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
// 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
// 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
// 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
// 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
// 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
// };
static Crc16()
{
ushort value;
ushort temp;
for (ushort i = 0; i < fcstab.Length; ++i)
{
value = 0;
temp = i;
for (byte j = 0; j < 8; ++j)
{
if (((value ^ temp) & 0x0001) != 0)
{
value = (ushort)((value >> 1) ^ polynomial);
}
else
{
value >>= 1;
}
temp >>= 1;
}
fcstab[i] = value;
}
}
/// <summary>Method that computes the checksum.</summary>
/// <param name="buff">The input <see cref="byte[]"/> to calculate the checksum off of.</param>
/// <example>
/// byte[] fcs = Crc16.ComputeChecksumBytes(buff)
/// </example>
/// <returns></returns>
public static byte[] ComputeChecksumBytes(byte[] buff)
{
ushort fcs = 0xFFFF;
for (int i = 0; i < buff.Length; i++)
{
byte index = (byte)((fcs ^ buff[i]) & 0xff);
fcs = (ushort)((fcs >> 8) ^ fcstab[index]);
}
fcs ^= 0xFFFF;
var lsb = (fcs >> 8) & 0xff;
var msb = fcs & 0xff;
return new byte[] { (byte)msb, (byte)lsb };
}
}
The good part is that the FCS table (fcstab[]) that gets generated is the same table seen in RFC 1662 thus confirming that the code in the constructor is correct.
The problem seems to be with the ComputeChecksumBytes() method.
I have an input PPP Packet of 7E FF 03 C0 21 01 00 00 0E 02 06 00 00 00 00 07 02 08 02 DD 31 7E.
I know from this link that the "FCS is calculated over the entire PPP packet, not including the start and stop flags (7E)." This leaves me with FF 03 C0 21 01 00 00 0E 02 06 00 00 00 00 07 02 08 02 DD 31.
I also know from that link that the FCS octets (DD 31) are to be "made equal to zero". This leaves me with FF 03 C0 21 01 00 00 0E 02 06 00 00 00 00 07 02 08 02 00 00.
When I call Crc16.ComputeChecksumBytes with that input byte array, my actual calculated FCS ends up being C0 0E.
Everything I'm doing seems to be correct but I still cannot figure out why I'm not getting the DD 31 that was calculated in the original packet.
Any help would be greatly appreciated!
Just do it without the two 0's at the end.
This is my first question on stack, so please to be understanding for me. I'm working on project that concern communication of smart card with reader. I have got Dell Smart Card Reader Keyboard and SIM card.
My project is created using C# and pcsc-sharp.dll.
My problem is the lack of response from the card to the transmitted bit sequence. Below I added sequences that sent successively to the smart card and responses.
Reader: Dell Smart Card Reader Keyboard 0
Command send: A0 C0 00 00 20
Response: 00 00 1F 3E 3F 00 01 00 0F 55 FF 01 15 B1 05 09 05 00 83 8A 83 8A 00 8A 00 00 00 00 00 00 00 00 90 00 (it's probably okay)
Command send: A0 A4 00 00 02 7F 20
Responde: 9F 22 (it's probably okay)
Rand Data send:
A0 88 00 00 10 09 05 01 0A 05 01 0D 06 00 0E 0E 08 00 0D 01 0A
Response: 9F 0C (it's probably okay)
Command send: A0 C0 00 00 0C
Response: 9F 0C (here is bug, this is not response for data that has been sent)
Does anybody know why is this happening? If anyone see any another bugs here, please described it. Below is fragment of my code in C#:
SCardContext context = new SCardContext();
context.Establish(SCardScope.System);
//Lista of available readers
string[] listOfReaders = context.GetReaders();
if (listOfReaders.Length <= 0)
{
throw new PCSCException(SCardError.NoReadersAvailable);
}
else
{
Console.WriteLine("Reader: " + listOfReaders[0]);
}
SCardReader reader = new SCardReader(context);
SCardError error = reader.Connect(listOfReaders[0], SCardShareMode.Exclusive, SCardProtocol.T0 | SCardProtocol.T1);
CheckErr(error);
IntPtr transmissionProtocol;
switch (reader.ActiveProtocol)
{
case SCardProtocol.T0:
transmissionProtocol = SCardPCI.T0;
break;
case SCardProtocol.T1:
transmissionProtocol = SCardPCI.T1;
break;
default:
throw new PCSCException(SCardError.ProtocolMismatch, reader.ActiveProtocol.ToString());
}
byte[] receivedData = new byte[256];
byte[] commandIntroduceYourself = new byte[] { 0xA0, 0xC0, 0x00, 0x00, 0x20 };
Console.Write("->");
for (int i = 0; i < commandIntroduceYourself .Length; i++)
{
Console.Write("{0:X2} ", start[i]);
}
error = czytnik.Transmit(transmissionProtocol, commandIntroduceYourself , ref receivedData);
Console.WriteLine();
Console.Write("<-");
for (int i = 0; i < receivedData.Length; i++)
{
Console.Write("{0:X2} ", receivedData[i]);
}
Console.WriteLine();
//This command below was required by the professor. I don't know why...
byte[] commandNext = new byte[] { 0xA0, 0xA4, 0x00, 0x00, 0x02, 0x7F, 0x20 };
Console.Write("->");
for (int i = 0; i < commandNext.Length; i++)
{
Console.Write("{0:X2} ", commandNext[i]);
}
error = czytnik.Transmit(transmissionProtocol, commandNext, ref receivedData);
Console.WriteLine();
Console.Write("<-");
for (int i = 0; i < receivedData.Length; i++)
{
Console.Write("{0:X2} ", receivedData[i]);
}
Console.WriteLine();
int amountOfDataToRand = 16;
//This is my function, never mind
string data = Randomize.RandomData(amountOfDataToRand);
byte[] dataSendToCard = Randomize.StringToByteArray(data);
byte[] newArray = new byte[dataSendToCard.Length + 5];
//Below is sequence that should be added to data
dataSendToCard.CopyTo(newArray, 5);
newArray[0] = 0xA0;
newArray[1] = 0x88;
newArray[2] = 0x00;
newArray[3] = 0x00;
newArray[4] = 0x10;
dataSendToCard = newArray;
Console.WriteLine("\nData send: ");
for (int i = 0; i < dataSendToCard.Length; i++)
{
Console.Write("{0:X2} ", dataSendToCard[i]);
}
Console.WriteLine();
error = czytnik.Transmit(transmissionProtocol, dataSendToCard, ref receivedData);
CheckErr(error);
Console.Write("Data received: ");
for (int i = 0; i < receivedData.Length; i++)
{
Console.Write("{0:X2} ", receivedData[i]);
}
Console.WriteLine();
byte[] commandGetResponse = new byte[] { 0xA0, 0xC0, 0x00, 0x00,0x0c };
Console.Write("->");
for (int i = 0; i < commandGetResponse.Length; i++)
{
Console.Write("{0:X2} ", commandGetResponse[i]);
}
error = czytnik.Transmit(transmissionProtocol, commandGetResponse, ref receivedData);
Console.WriteLine();
Console.Write("<-");
for (int i = 0; i < receivedData.Length; i++)
{
Console.Write("{0:X2} ", receivedData[i]);
}
Console.WriteLine();
I read this document, but I didn't find answer. http://www.embedx.com/pdfs/ISO_STD_7816/info_isoiec7816-4%7Bed21.0%7Den.pdf
I've tried hours to figure out how to manipulate a byte array to do the "unpacking" and packing with C#.
Packed Data Format
Data is packed in 8 byte “packets”, with the MS bit stripped from 7
parameter bytes, and packed into an eighth byte, which is sent at the start
of the 8 byte packet.
Example:
Input Data
1 A7 A6 A5 A4 A3 A2 A1 A0
2 B7 B6 B5 B4 B3 B2 B1 B0
3 C7 C6 C5 C4 C3 C2 C1 C0
4 D7 D6 D5 D4 D3 D2 D1 D0
5 E7 E6 E5 E4 E3 E2 E1 E0
6 F7 F6 F5 F4 F3 F2 F1 F0
7 G7 G6 G5 G4 G3 G2 G1 G0
Packed MIDI data
1 00 G7 F7 E7 D7 C7 B7 A7
2 00 A6 A5 A4 A3 A2 A1 A0
3 00 B6 B5 B4 B3 B2 B1 B0
4 00 C6 C5 C4 C3 C2 C1 C0
5 00 D6 D5 D4 D3 D2 D1 D0
6 00 E6 E5 E4 E3 E2 E1 E0
7 00 F6 F5 F4 F3 F2 F1 F0
8 00 G6 G5 G4 G3 G2 G1 G0
Each row indicates one byte, each column one bit (MSB first).
How do I implement this conversion?
If I'm reading the spec right, this should do the trick:
byte[] input = new byte[7] { 0x81, 0x82, 0x03, 0x84, 0x05, 0x06, 0x87 };
byte[] output = new byte[8];
for (int i = 0; i < 7; i++)
{
output[0] |= (byte)((input[i] >> 7) << i);
output[i + 1] = (byte)(input[i] & 0x7F);
}
// output == { 0x4b, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }
// output[0] == 0b01001011
As you can see, the most significant bit of each input byte in the example is cleared, and a prefix byte is added with the most significant bit of each input byte.
I can say I don't know what I'm asking for help,because I don't know the format,but I've got a picture.
I have a byte[] array ,how do I convert it to that format below(in right)?
alt text http://img512.imageshack.us/img512/3548/48667724.jpg
Its not plain ascii.
It sounds like you'd like to take an array of bytes, and convert it to text (replacing characters outside of a certain range with "."s)
static public string ConvertFromBytes(byte[] input)
{
StringBuilder output = new StringBuilder(input.Length);
foreach (byte b in input)
{
// Printable chars are from 0x20 (space) to 0x7E (~)
if (b >= 0x20 && b <= 0x7E)
{
output.Append((char)b);
}
else
{
// This isn't a text char, so use a placehold char instead
output.Append(".");
}
}
return output.ToString();
}
or as a LINQy extension method (inside a static extension class):
static public string ToPrintableString(this byte[] bytes)
{
return Encoding.ASCII.GetString
(
bytes.Select(x => x < 0x20 || x > 0x7E ? (byte)'.' : x)
.ToArray()
);
}
(You could call that like string printable = byteArray.ToPrintableString();)
Use b.ToString("x2") to format a byte value into a two character hexadecimal string.
For the ASCII display, check if the value corresponds to a regular printable character and convert it if it is:
if (b >= 32 && b <= 127) {
c = (char)b;
} else {
c = '.';
}
Or shorter:
c = b >= 32 && b <= 127 ? (char)b : '.';
To do it on an array:
StringBuilder builder = new StringBuilder();
foreach (b in theArray) {
builder.Append(b >= 32 && b <= 127 ? (char)b : '.');
}
string result = builder.ToString();
This could be any number of encodings... try this test test script to see which of them print out:
Bl8s
Here is the script:
byte[] b = new byte[] {0x42, 0x6C, 0x38, 0x73 };
foreach (EncodingInfo ei in Encoding.GetEncodings())
{
Console.WriteLine("{0} - {1}", ei.GetEncoding().GetString(b), ei.Name);
}
[edit 2018:] Re-wrote the function from scratch to make the code much more efficient and fix some other problems. You can now also optionally specify a starting offset and number of bytes (starting from there) to display.
If you want the whole memory display, including the offset number, and left and right displays, you can do it like this: (32-byte width)
/// <summary> Returns a String where the specified bytes are formatted in a
/// 3-section debugger-style aligned memory display, 32-bytes per line </summary>
public static unsafe String MemoryDisplay(byte[] mem, int i_start = 0, int c = -1)
{
if (mem == null)
throw new ArgumentNullException();
if (i_start < 0)
throw new IndexOutOfRangeException();
if (c == -1)
c = mem.Length - i_start;
else if (c < 0)
throw new ArgumentException();
if (c == 0)
return String.Empty;
char* pch = stackalloc Char[32]; // for building right side at the same time
var sb = new StringBuilder((c / 32 + 1) * 140); // exact pre-allocation
c += i_start;
for (int i = i_start & ~0x1F; i < c;)
{
sb.Append(i.ToString("x8"));
sb.Append(' ');
do
{
if (i < i_start || i >= c) // non-requested area, or past the end
{
sb.Append(" ");
pch[i & 0x1F] = ' ';
}
else
{
var b = mem[i];
sb.Append(b.ToString("x2") + " ");
pch[i & 0x1F] = non_monospace(b) ? '.' : (Char)b;
}
}
while ((++i & 0x1F) != 0);
sb.Append(' ');
sb.AppendLine(new String(pch, 0, 32));
}
return sb.ToString();
}
The code uses the following helpers to determine which characters should be shown as 'dots' in right-hand part.
static readonly ulong[] _nmb =
{
0x00000000ffffe7ffUL,
0x8000000000000000UL,
0x00002000ffffffffUL,
0x0000000000000000UL,
};
static bool non_monospace(byte b) => (_nmb[b >> 6] & 1UL << b) != 0;
Output of the above function looks like this (character width is 138 columns, scroll to the right to see the "human-readable" part):
00000000 47 49 46 38 39 61 0f 00 0f 00 91 ff 00 00 00 00 c0 c0 c0 ff ff 00 00 00 00 21 f9 04 01 00 00 01 GIF89a...................!......
00000020 00 2c 00 00 00 00 0f 00 0f 00 00 02 2c 8c 0d 99 c7 91 02 e1 62 20 5a 79 ea bd 00 6d 89 69 8a f8 .,..........,.......b Zy...m.i..
00000040 08 e5 a7 99 e9 17 9d ac 24 a2 21 68 89 1e ac b4 d9 db 51 ab da c8 8c 1a 05 00 3b ........$.!h......Q.......;
Try: Encoding.Default.GetBytes
If that doesn't work, there are different types that you can specify (UTF-8, ASCII...)