Generar CRC16 y vuelta atras

Generar CRC16 y vuelta atras

Postby JmGarcia » Thu Aug 11, 2011 9: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
User avatar
JmGarcia
 
Posts: 654
Joined: Mon May 29, 2006 3:14 pm
Location: Madrid - ESPAÑA

Re: Generar CRC16 y vuelta atras

Postby Antonio Linares » 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
User avatar
Antonio Linares
Site Admin
 
Posts: 41898
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: Generar CRC16 y vuelta atras

Postby Antonio Linares » 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
User avatar
Antonio Linares
Site Admin
 
Posts: 41898
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain

Re: Generar CRC16 y vuelta atras

Postby JmGarcia » 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 :-)
:oops:

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: Select all  Expand view
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
User avatar
JmGarcia
 
Posts: 654
Joined: Mon May 29, 2006 3:14 pm
Location: Madrid - ESPAÑA


Return to FiveWin para Harbour/xHarbour

Who is online

Users browsing this forum: No registered users and 67 guests