How to get the same result in VBA and in PHP computing a CCITT CRC checksum

Internet, Microsoft, Software

I was working last week on a Microsoft Access application and I needed to get some data from a webserver running Apache/PHP. Exchanging data with the server was easy, the WinHTTP and XML ActiveX library components are really cool and easy to use for that. But then I came unto some unexpected trouble when I tried to use a CRC check on both the VBA and PHP side to quickly add some integrity checking on the exchanged data.

I already had a VBA routine computing a CRC checksum, but had none on the PHP side. So I thought “google it up”, pick the first CRC checksum routine that comes up and use it, easy. By the way, if you want to refresh your neurons about the CRC stuff, you can read more about that in wikipedia.

To make a long story short, there are many algorithms out there, for VBA and PHP, and to find two that go well along and yield the same result, it takes some time and tries.

So, here are the two ones I now use. Enjoy !

Note: replace “&” with “&” in the code, it’s a wordpress problem, sorry.

VBA:

'Compute a CRC for a string (16bits CRC, CCITT inverted)
'Original source: 'http://www.xtremevbtalk.com/showthread.php?t=318655
'Added string param instead od byte array, ErrHandler and second optional parameter InputCrc
Private Function CRC16_2(ByVal psData As String, Optional ByVal plInitCrc As Variant) As Long
Const CRC_POLYNOM As Long = &H8408&
Const CRC_PRESET As Long = &HFFFF&
Dim crc As Long, i As Long, j As Long
Dim Buffer() As Byte

On Error GoTo ErrHandler

Buffer = StrConv(psData, vbFromUnicode)

If IsMissing(plInitCrc) Then
crc = CRC_PRESET 'unsigned internal CRC = CRC_PRESET
Else
crc = plInitCrc
End If
For i = 0 To UBound(Buffer) 'for(i=0; i < cnt; i++)
crc = crc Xor Buffer(i) 'crc ^= Buffer[i]
For j = 0 To 7 'for(j=0; j<8;j++)
If (crc And 1) Then 'if(crc & 0x0001)
crc = (crc \ 2) Xor CRC_POLYNOM 'crc=(crc>>1)^CRC_POLYNOM;
Else
crc = (crc \ 2) 'crc=(crc>>1)
End If
Next j
Next i
CRC16_2 = crc
ErrHandler:
End Function

And in PHP:

// CCITT, X24
define('CRC16POLYI',0x8408);

/*
* Source: https://forums.digitalpoint.com/threads/php-define-function-calculate-crc-16-ccitt.2584389/
* Note: no second parameter here as on the VBA version
*/
function CRC16Inverse($buffer) {
$result = 0xFFFF;
if ( ($length = strlen($buffer)) > 0) {
for ($offset = 0; $offset < $length; $offset++) {
$result ^= ord($buffer[$offset]);
for ($bitwise = 0; $bitwise < 8; $bitwise++) {
$lowBit = $result & 0x0001;
$result >>= 1;
if ($lowBit) {
$result ^= CRC16POLYI;
}
}
}
}
return $result;
}

Comments on this entry are closed.