FiveTech Support Forums

FiveWin / Harbour / xBase community
Board index FiveWin para Harbour/xHarbour Generar CRC16 y vuelta atras
Posts: 654
Joined: Mon May 29, 2006 03:14 PM
Generar CRC16 y vuelta atras
Posted: Thu Aug 11, 2011 09:36 AM

驴 Existe alguna funci贸n que partiendo de los dos bytes de un CRC16 decodifique el string dado ?
...y ya puestos la que genera CRC16 y obtiene los dos bytes del CRC.

Gracias.

Mi abuelo dec铆a: Los aviones vuelan porque Dios quiere, y los helic贸pteros ni Dios sabe porque vuelan.

FWH 16.02, xHarbour 1.2.3, Harbour 3.2.0, WorkShop 4.5, AJ Make 0.30, Borlan BCC 7.00, VisualStudio 2013
Posts: 44158
Joined: Thu Oct 06, 2005 05:47 PM
Re: Generar CRC16 y vuelta atras
Posted: Thu Aug 11, 2011 10:14 AM

Salvo que me equivoque, no existe forma de obtener la cadena original a partir de su CRC :-)

De la misma forma que de la letra del DNI no se puede obtener el n煤mero del DNI

regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 44158
Joined: Thu Oct 06, 2005 05:47 PM
Re: Generar CRC16 y vuelta atras
Posted: Thu Aug 11, 2011 10:16 AM
FiveWin te proporciona nStrCRC16( cString ) --> nCRC16 y nStrCRC( cString ) --> nCRC (32 bits)

http://wiki.fivetechsoft.com/doku.php?id=fivewin_function_nstrcrc
regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 654
Joined: Mon May 29, 2006 03:14 PM
Re: Generar CRC16 y vuelta atras
Posted: Thu Aug 11, 2011 11:22 AM
Antonio Linares wrote:Salvo que me equivoque, no existe forma de obtener la cadena original a partir de su CRC :-)
:-)

Pues no dispongo de la cadena original, las cadenas a decodificar ser铆an de 7 o 14 bytes.
No es para comprobar la integridad de las cadenas sino para decodificarla.

Tengo el c贸digo PERL que lo hace pero no se pasarlo a FWH/xHarbour, creo que es la funcion "rx_decode" a la que se le pasa la cadena y los dos bytes del CRC16:
Code (fw): Select all Collapse
http://topic.csdn.net/u/20110316/02/eab0b8c6-9b21-4b7d-9bab-06a9ae556638.html

Perl code
#!/usr/bin/perl -w
#
# TCP Proxy Server for reverse engineering the Kinetic SBS-1e receiver
# Mark Street <marksmanuk@gmail.com>
#

use strict;
use Getopt::Std;
use IO::Socket;
use IO::Handle;

my $local_port 聽 聽= 10001;
my $target_ip 聽 聽= "141.22.13.108";
my $target_port 聽 聽= 10001;

my $MSG_LOGIN1 = "\x01\xE9\x5D\xC5\x53\xB1\xD7\xB7\x4E"; 聽 聽# Type 0x17

# Connect to SBS-1 as a TCP client:
#print "$0 Version 0.9.1 <marksmanuk\@gmail.com>\n";
#print "Connecting to SBS-1 on $target_ip:$target_port\n";

my $remote = IO::Socket::INET->new(
聽 聽 Proto 聽 聽=> "tcp",
聽 聽 PeerAddr => "$target_ip",
聽 聽 PeerPort => "$target_port" )
聽 聽 || die "Cannot connect to $target_ip:$target_port";

# Local decode mode
local_decode();

# ----------------------------------------------------------------------------
# Communicate with SBS-1 directly
# ----------------------------------------------------------------------------

sub local_decode
{
聽 聽 # Send Login1 string to SBS-1 and await reply.
聽 聽 # Reply will contain keys to be used to decode next reply.

聽 聽 # Magic keys: 聽 聽0x4857 = "HW"
聽 聽 # Magic keys: 聽 聽0x5958 = "YX"
聽 聽 # Magic keys: 聽 聽0x4431 = "D1"
聽 聽 # Magic keys: 聽 聽0x474A = "GJ"

聽 聽 #print "Sending Login 1 message...\n";
聽 聽 send_sbs(0x17, $MSG_LOGIN1, 0x4857, 0x5958);
聽 聽 my $rx = recv_sbs(0x27, 0x4431, 0x474A);

聽 聽 # Subsequent keys are returned in reply to login message:
聽 聽 # Tx Key = 5DE9 / 53C5
聽 聽 # Rx Key = 5D0D / 61FE

聽 聽 my @msg = split //,$rx->{msg};
聽 聽 my $tx_key1 = (ord ($msg[2]) << 8) + ord $msg[1]; 聽 聽
聽 聽 my $tx_key2 = (ord ($msg[4]) << 8) + ord $msg[3];
聽 聽 
聽 聽 my $rx_key1 = (ord ($msg[10]) << 8) + ord $msg[9]; 聽 聽
聽 聽 my $rx_key2 = (ord ($msg[12]) << 8) + ord $msg[11];

聽 聽 # Send Login2 message and await reply. 聽Encoding will be:
聽 聽 # 02 - Key1, Key 2 - Key3, Key 4 

聽 聽 #print "Sending Login 2 message...\n";
聽 聽 my $MSG_LOGIN2 = "\x02".substr($rx->{msg}, 9, 8);
聽 聽 send_sbs(0x18, $MSG_LOGIN2, $tx_key1, $tx_key2);

聽 聽 # Reply will contain inventory details.
聽 聽 $rx = recv_sbs(0x28, $rx_key1, $rx_key2);

聽 聽 my ($serial, $firmware, $build, $fpga1, $fpga2, $decoder1, $decoder2, $user1, $user2) = 
聽 聽 聽 聽 unpack "xA8A16SCCCCCC", $rx->{msg};

聽 聽 print "\tSerial Number: $serial\n";
聽 聽 print "\tFirmware: 聽 聽 聽$firmware\n";
聽 聽 print "\tBuild: 聽 聽 聽 聽 $build\n";
聽 聽 printf "\tFPGA: 聽 聽 聽 聽 聽%d.%02d\n", $fpga1, $fpga2;
聽 聽 printf "\tDecoder: 聽 聽 聽 %d.%02d\n", $decoder1, $decoder2;
聽 聽 printf "\tUser F/W: 聽 聽 聽%d.%02d\n", $user1, $user2;

聽 聽 # We're logged in. 聽Wait for unsolicted events to come in.
聽 聽 print "Awaiting events...\n";

聽 聽 while(1)
聽 聽 {
聽 聽 聽 聽 #print "-"x78,"\n" if $args{v};
聽 聽 聽 聽 $rx = recv_sbs(undef, $rx_key1, $rx_key2);

聽 聽 # 聽 聽next unless $rx->{type} == 0x01;

聽 聽 # 聽 聽printf "Received Event: 0x%02X\n", $rx->{type};
聽 聽 聽 聽 Dump($rx->{msg});
聽 聽 }

聽 聽 exit;
}

# ----------------------------------------------------------------------------
# Local Receive Functions
# ----------------------------------------------------------------------------

my $rx_buffer = "";

sub recv_sbs
{
聽 聽 my $expected 聽 聽 = shift;
聽 聽 my $key1 聽 聽 聽 聽 = shift;
聽 聽 my $key2 聽 聽 聽 聽 = shift;

聽 聽 # SBS-1 can send bursts of messages that can arrive in a single
聽 聽 # concatenated packet from the socket. 聽We receive a fixed amount of data
聽 聽 # from the socket to a buffer then return complete messages to the caller.

聽 聽 my $buffer;
聽 聽 my $msg_type;
聽 聽 my $rx_msg;

聽 聽 while(1)
聽 聽 {
聽 聽 聽 聽 #printf "Waiting for Message Type 0x%02X...\n", $expected 
聽 聽 聽 聽 # 聽 聽if defined $expected && $args{v};
聽 聽 聽 聽 recv($remote, $buffer, 1500, 0);
聽 聽 聽 聽 $rx_buffer .= $buffer;

聽 聽 聽 聽 die "Disconnected!" if length($buffer) == 0;

聽 聽 聽 聽 # Find end of message: 聽Remember 0x10 is escaped
聽 聽 聽 聽 next unless $rx_buffer =~ m/(?<!\x10)\x10\x03/g;

聽 聽 聽 聽 # This is hack to extract a complete un-escaped message including CRC.
聽 聽 聽 聽 my @val = split //,$rx_buffer;
聽 聽 聽 聽 my ($flag, $idx);
聽 聽 聽 聽 my $at_crc = 0;
聽 聽 聽 聽 $rx_msg = "";

聽 聽 聽 聽 for ($idx=0; $idx<length($rx_buffer); $idx++)
聽 聽 聽 聽 {
聽 聽 聽 聽 聽 聽 if ($val[$idx] eq "\x10" && $flag)
聽 聽 聽 聽 聽 聽 {
聽 聽 聽 聽 聽 聽 聽 聽 $flag = 0;
聽 聽 聽 聽 聽 聽 聽 聽 next;
聽 聽 聽 聽 聽 聽 }

聽 聽 聽 聽 聽 聽 $at_crc++ if $at_crc; 聽 聽 聽 聽# 2 & 3
聽 聽 聽 聽 聽 聽 last if $at_crc == 4;

聽 聽 聽 聽 聽 聽 if ($val[$idx] eq "\x03" && $flag)
聽 聽 聽 聽 聽 聽 {
聽 聽 聽 聽 聽 聽 聽 聽 $at_crc = 1; 聽 聽
聽 聽 聽 聽 聽 聽 }

聽 聽 聽 聽 聽 聽 if ($val[$idx] eq "\x10") {
聽 聽 聽 聽 聽 聽 聽 聽 $flag = 1;
聽 聽 聽 聽 聽 聽 } else {
聽 聽 聽 聽 聽 聽 聽 聽 $flag = 0;
聽 聽 聽 聽 聽 聽 }

聽 聽 聽 聽 聽 聽 $rx_msg .= $val[$idx];
聽 聽 聽 聽 }

聽 聽 聽 聽 # Chop message from buffer;
聽 聽 聽 聽 $rx_buffer = substr($rx_buffer, $idx, length($rx_buffer)-$idx);
聽 聽 聽 聽 $rx_buffer = "" if (length($rx_buffer) > 10000);

聽 聽 聽 聽 $msg_type = ord substr($rx_msg, 2, 1);

聽 聽 聽 聽 # Block until we receive specified message type:
聽 聽 聽 聽 last unless defined $expected;
聽 聽 聽 聽 last if defined $expected && $msg_type == $expected;
聽 聽 }

聽 聽 # Got it. 聽Strip the header and footer and separate into various parts:
聽 聽 my @msg = split //,$rx_msg;
聽 聽 my $rx_crc16 = (ord($msg[-2]) << 8) + ord($msg[-1]);

聽 聽 shift @msg; shift @msg; shift @msg;
聽 聽 pop @msg; pop @msg; pop @msg; pop @msg;

聽 聽 $rx_msg = join "",@msg;


聽 聽 # Descramble received message:
聽 聽 my $rx_clr = rx_decode($rx_msg, $key1, $key2);

聽 聽 # Verify received checksum:
聽 聽 my $crc16 = crc16(0x0000, 0x1021, $msg_type);
聽 聽 foreach my $byte (split //,$rx_clr)
聽 聽 {
聽 聽 聽 聽 $crc16 = crc16($crc16, 0x1021, ord $byte);
聽 聽 }
聽 聽 return { msg => $rx_clr, crc => $crc16, type => $msg_type };
}

sub rx_decode
{
聽 聽 my $rx_msg 聽 聽 = shift;
聽 聽 my $key1 聽 聽= shift;
聽 聽 my $key2 聽 聽= shift;

聽 聽 die "Undefined Message Bytes" 聽 聽 unless defined $rx_msg;

聽 聽 # Descramble payload bytes. 聽This is perfomed in a similar way to the
聽 聽 # encoder by calling the CRC routine initially with magic values
聽 聽 # then doing some bit shifts and logic.
聽
聽 聽 my $enc1 = 0; 聽 聽 聽 聽 聽 聽# Defaults to 0

聽 聽 my $rx_clr;

聽 聽 # Take each message byte in turn and descramble:
聽 聽 foreach my $byte (split //,$rx_msg)
聽 聽 {
聽 聽 聽 聽 $byte = ord $byte;

聽 聽 聽 聽 # Starting with the magic init values, use the returned
聽 聽 聽 聽 # CRC16 as the init values for the next round.

聽 聽 聽 聽 $key1 = crc16($key1, 0x1021, 0xFF);
聽 聽 聽 聽 $key2 = crc16($key2, 0x8005, 0xFF);

聽 聽 聽 聽 # Now some bit shifting weirdness:
聽 聽 聽 聽 my $enc2 = ($enc1 >> 3) | ($enc1 << 5);

聽 聽 聽 聽 # And some XORing for good measure:
聽 聽 聽 聽 my $enc3 = ($byte ^ $enc2) & 0xFF;
聽 聽 聽 聽 my $enc4 = ($enc3 ^ $key1) & 0xFF;
聽 聽 聽 聽 my $enc5 = ($enc4 ^ $key2) & 0xFF;
聽 聽 聽 聽 $enc1 聽 聽= ($enc2 ^ $enc5) & 0xFF;
聽 聽 聽 聽 $rx_clr .= chr $enc5;
聽 聽 }

聽 聽 return $rx_clr;
}

# ----------------------------------------------------------------------------
# Local Send Functions
# ----------------------------------------------------------------------------

sub send_sbs
{
聽 聽 my $msg_type 聽 聽 = shift;
聽 聽 my $msg 聽 聽 聽 聽 = shift;
聽 聽 my $key1 聽 聽 聽 聽= shift;
聽 聽 my $key2 聽 聽 聽 聽= shift;

聽 聽 # Scramble payload
聽 聽 #printf "Using key1=0x%04X and key2=0x%04X\n", $key1, $key2 if $args{v};
聽 聽 my $enc_login1 = tx_encode($msg_type, $msg, $key1, $key2);

聽 聽 # 16 bit message checksum works like this:
聽 聽 # CRC16 Poly 0x1021 Init 0x0000 聽 聽- Message Type + Msg Payload aginst
聽 聽 # the cleartext bytes.

聽 聽 my $crc16 = crc16(0x0000, 0x1021, $msg_type);
聽 聽 foreach my $byte (split //,$msg)
聽 聽 {
聽 聽 聽 聽 $crc16 = crc16($crc16, 0x1021, ord $byte);
聽 聽 }

聽 聽 #printf "CRC16 after msg payload = 0x%04X\n", $crc16 if $args{v};

聽 聽 # Add the header and footer bytes and 
聽 聽 my $buffer = "\x10\x02".(chr $msg_type)."$enc_login1\x10\x03".
聽 聽 聽 聽 chr($crc16 >> 8).chr($crc16 & 0xFF);

聽 聽 print $remote $buffer;
}

sub tx_encode
{
聽 聽 my $msg_type = shift;
聽 聽 my $msg 聽 聽 聽= shift;
聽 聽 my $key1 聽 聽 = shift;
聽 聽 my $key2 聽 聽 = shift;
聽 聽 
聽 聽 die "Undefined Message Type ID" unless defined $msg_type;
聽 聽 die "Undefined Message Bytes" 聽 聽 unless defined $msg;

聽 聽 my $len = length($msg);

聽 聽 # The message payload, but not the Message Type ID, are now scrambled
聽 聽 # by calling the usual CRC routine with various initialisation words and
聽 聽 # by performing a series of bit shifts.

聽 聽 my $enc1 = 0; 聽 聽 聽 聽 聽 聽# Defaults to 0
聽 聽 my $output;

聽 聽 # Take each message byte in turn and scramble:
聽 聽 foreach my $byte (split //,$msg)
聽 聽 {
聽 聽 聽 聽 $byte = ord $byte;
聽 聽 聽 聽 #printf "Scrambling 0x%02X\n", $byte if $args{v};

聽 聽 聽 聽 # Starting with the magic init values, use the returned
聽 聽 聽 聽 # CRC16 as the init values for the next round.

聽 聽 聽 聽 $key1 = crc16($key1, 0x1021, 0xFF);
聽 聽 聽 聽 $key2 = crc16($key2, 0x8005, 0xFF);

聽 聽 聽 聽 # Now some bit shifting weirdness:
聽 聽 聽 聽 my $enc2 = ($enc1 >> 3) | ($enc1 << 5);

聽 聽 聽 聽 # And some XORing for good measure:
聽 聽 聽 聽 $enc1 聽 聽= ($byte ^ $enc2) & 0xFF;
聽 聽 聽 聽 my $enc3 = ($enc1 ^ $key1) & 0xFF;
聽 聽 聽 聽 my $enc4 = ($enc3 ^ $key2) & 0xFF;

# 聽 聽 聽 聽printf "\tScrambled 0x%02X = 0x%02X\n", $byte, $enc4 & 0xFF if $args{v};
聽 聽 聽 聽 $output .= chr $enc4;
聽 聽 }

聽 聽 return $output;
}

# ----------------------------------------------------------------------------
# Helpers
# ----------------------------------------------------------------------------

sub crc16
{
聽 聽 my $init = shift;
聽 聽 my $poly = shift;
聽 聽 my $val 聽= shift;

聽 聽 die "Undefined CRC value" 
聽 聽 聽 聽 unless defined $val && defined $poly && defined $init;

聽 聽 my $var;
聽 聽 for (my $i=0; $i<8; $i++)
聽 聽 {
聽 聽 聽 聽 $var = $val << 8;
聽 聽 聽 聽 $var ^= $init;
聽 聽 聽 聽 $init += $init;
聽 聽 聽 聽 $val <<= 1;

聽 聽 聽 聽 if ($var & 0x8000)
聽 聽 聽 聽 {
聽 聽 聽 聽 聽 聽 $init ^= $poly;
聽 聽 聽 聽 }
聽 聽 }

聽 聽 return $init & 0xFFFF;
}

sub Dump
{
聽 聽 my $buffer = shift;
聽 聽 my $header = shift;

聽 聽 die "Undefined buffer" unless defined $buffer;
聽 聽 die "References not supported" unless ref $buffer eq "";

聽 聽 my @vals = unpack("C*", $buffer);
聽 聽 print "$header\n" if defined $header;

聽 聽 my $rowChars = 18;
聽 聽 my $pos = 0;

聽 聽 while ($pos < @vals)
聽 聽 {
聽 聽 聽 聽 #printf "%04X: ", $pos;

聽 聽 聽 聽 for (my $i=0; $i<$rowChars; $i++)
聽 聽 聽 聽 {
聽 聽 聽 聽 聽 聽 (($pos+$i) < @vals) ? 
聽 聽 聽 聽 聽 聽 聽 聽 printf "%02X,", $vals[$pos+$i] : print " 聽 ";
聽 聽 聽 聽 } 聽 聽
聽 聽 聽 聽 $pos += $rowChars;
聽 聽 聽 聽 print "\n";
聽 聽 }
}
Mi abuelo dec铆a: Los aviones vuelan porque Dios quiere, y los helic贸pteros ni Dios sabe porque vuelan.

FWH 16.02, xHarbour 1.2.3, Harbour 3.2.0, WorkShop 4.5, AJ Make 0.30, Borlan BCC 7.00, VisualStudio 2013

Continue the discussion