1 |
dpavlin |
7 |
#!/usr/bin/perl -w |
2 |
|
|
|
3 |
|
|
# guess-crc.pl |
4 |
|
|
# |
5 |
|
|
# 09/28/08 21:54:24 CEST Dobrica Pavlinusic <dpavlin@rot13.org> |
6 |
|
|
|
7 |
dpavlin |
13 |
# CRC info from: http://stackoverflow.com/questions/149617/how-could-i-guess-a-checksum-algorithm |
8 |
|
|
# and from: http://www.geocities.com/SiliconValley/Pines/8659/crc.htm |
9 |
|
|
|
10 |
|
|
# LRC: Polynomial=0x81; 8 bits; Normal; Initial=0; Final=as calculated |
11 |
|
|
# CRC16: Polynomial=0xa001; 16 bits; Normal; Initial=0; Final=as calculated |
12 |
|
|
# CCITT: Polynomial=0x1021; 16 bits; reverse; Initial=0xffff; Final=0x1d0f |
13 |
|
|
# Xmodem: Polynomial=0x1021; 16 bits; reverse; Initial=0; Final=0x1d0f |
14 |
|
|
# CRC32: Polynomial=0xebd88320; 32 bits; Normal; Initial=0xffffffff; Final=inverted value |
15 |
|
|
# ZIP32: Polynomial=0x04c11db7; 32 bits; Normal; Initial=0xffffffff; Final=as calculated |
16 |
|
|
|
17 |
|
|
# IPX: Polynomial=0x8005; 16 bits; Reverse; Initial=0xffff; Final=as calculated |
18 |
|
|
# ISO 18000-6B: Polynomial=0x1021; 16 bits; Reverse; Initial=0xffff; Final=as calculated |
19 |
|
|
# ISO 18000-6C: Polynomial=0x1021; 16 bits; Reverse; Initial=0xffff; Final=as calculated |
20 |
|
|
# Data must be padded with zeroes to make a multiple of 8 bits |
21 |
|
|
# ISO CRC5: Polynomial=custom; 5 bits; Reverse; Initial=0x9; Final=shifted left by 3 bits |
22 |
|
|
# Data must be padded with zeroes to make a multiple of 8 bits |
23 |
|
|
# EPC class 1: Polynomial=custom 0x1021; 16 bits; Reverse; Initial=0xffff; Final=post processing of 16 zero bits |
24 |
|
|
|
25 |
dpavlin |
7 |
use strict; |
26 |
|
|
|
27 |
|
|
use Digest::CRC qw(crc32 crc16 crcccitt crc crc8); |
28 |
|
|
use Data::Dump qw/dump/; |
29 |
dpavlin |
13 |
use File::Slurp; |
30 |
dpavlin |
7 |
|
31 |
dpavlin |
12 |
my $debug = 1 if @ARGV; |
32 |
|
|
|
33 |
dpavlin |
7 |
sub hex2b { |
34 |
|
|
my $hex = shift; |
35 |
|
|
return map { hex($_) } split(/\s+/, $hex); |
36 |
|
|
} |
37 |
|
|
|
38 |
dpavlin |
12 |
my @check_polys = ( 0x0000 .. 0xffff ); |
39 |
dpavlin |
13 |
#@check_polys = ( 32833, 43271, 32833, 43271, 19299, 35925, 47123, 49319, 56971 ); # crc16 |
40 |
|
|
@check_polys = ( 31125, 53345, 11642, 24337, 51699, 55122, 15257 ); # ccitt |
41 |
dpavlin |
7 |
|
42 |
dpavlin |
12 |
my @check_offset = ( 0,1,2,3 ); |
43 |
|
|
@check_offset = ( 1 ); # skip first, second always zero |
44 |
|
|
|
45 |
dpavlin |
13 |
my @try_polys = ( |
46 |
|
|
{ name => "CRC-16/CITT", width => 16, poly => 0x1021, init => 0xFFFF, refin => 0, refout => 0, xorout => 0x0000 }, |
47 |
|
|
{ name => "XMODEM", width => 16, poly => 0x8408, init => 0x0000, refin => 1, refout => 1, xorout => 0x0000 }, |
48 |
|
|
{ name => "ARC", width => 16, poly => 0x8005, init => 0x0000, refin => 1, refout => 1, xorout => 0x0000 }, |
49 |
|
|
{ name => "CRC-16", width => 16, poly => 0xA001, init => 0x0000, refin => 0, refout => 0, xorout => 0x0000 }, |
50 |
|
|
); |
51 |
|
|
|
52 |
|
|
my @data = ( |
53 |
|
|
'D5 00 05 04 00 11 8C 66', |
54 |
|
|
'D6 00 05 FE 00 05 FA 40', |
55 |
|
|
); |
56 |
|
|
#@data = read_file('all.out') if -e 'all.out'; |
57 |
|
|
|
58 |
dpavlin |
12 |
my $found_polys; |
59 |
|
|
|
60 |
|
|
sub check_crc { |
61 |
|
|
my ( $poly, $bytes, $wanted ) = @_; |
62 |
|
|
my $ctx = Digest::CRC->new( |
63 |
|
|
#width=>16, init=>0xffff, xorout=>0, refout=>1, poly=>0x1021, refin=>0 # ccitt |
64 |
|
|
#width=>16, init=>0, xorout=>0, refout=>1, poly=>0x8005, refin=>1 # crc16 |
65 |
|
|
#0x8408, |
66 |
|
|
#0xa001, |
67 |
dpavlin |
13 |
#width=>16, init=>0, xorout=>0, refout=>1, poly=>$poly,refin=>1 # crc16 |
68 |
|
|
width=>16, init=>0xffff, xorout=>0, refout=>1, poly=>$poly, refin=>0 # ccitt |
69 |
dpavlin |
12 |
); |
70 |
|
|
$ctx->add( $bytes ); |
71 |
|
|
my $try = $ctx->digest; |
72 |
dpavlin |
13 |
my $n = pack('n*', $try); |
73 |
|
|
my $v = pack('n*', $try); |
74 |
|
|
warn "## check_crc( $poly, ",dump($bytes)," ) = ",dump( $n, $v, $wanted ) if $debug; |
75 |
|
|
return $n eq $wanted || $v eq $wanted; |
76 |
dpavlin |
12 |
} |
77 |
|
|
|
78 |
dpavlin |
13 |
foreach ( @data ) { |
79 |
|
|
|
80 |
dpavlin |
7 |
my $hex = $_; |
81 |
|
|
$hex =~ s/\s+//g; |
82 |
|
|
|
83 |
|
|
my $bytes = pack('H*', substr($hex, 0, -4)); |
84 |
|
|
|
85 |
dpavlin |
13 |
print "?? guess crc ",substr($hex,-4),"\n"; |
86 |
dpavlin |
7 |
my $crc = pack('H4', substr($hex,-4)); |
87 |
|
|
|
88 |
dpavlin |
13 |
warn "input $_ => ",dump( $bytes, $crc ) if $debug; |
89 |
dpavlin |
7 |
|
90 |
dpavlin |
12 |
foreach my $o ( @check_offset ) { |
91 |
dpavlin |
7 |
my $b = substr( $bytes, $o ); |
92 |
|
|
|
93 |
dpavlin |
12 |
foreach my $poly ( @check_polys ) { |
94 |
dpavlin |
7 |
|
95 |
|
|
print "## poly $poly\n" if $poly % 1000 == 0; |
96 |
|
|
|
97 |
dpavlin |
12 |
if ( check_crc( $poly, $b, $crc ) ) { |
98 |
|
|
warn "HIT: $o poly: $poly\n"; |
99 |
|
|
$found_polys->{$poly}->{$o}++; |
100 |
dpavlin |
7 |
} |
101 |
|
|
} |
102 |
|
|
} |
103 |
|
|
} |
104 |
|
|
|
105 |
dpavlin |
12 |
print "FOUND polys = ", dump( $found_polys ); |