crc 0.2 → 0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9,7 +9,7 @@
9
9
  # \* \* \* \* \* \* \* \*
10
10
  #
11
11
  # Ruby implemented CRC generator.
12
- # It's used slice-by-16 algorithm with byte-order free and byte-alignment free.
12
+ # It's used slice-by-16 algorithm with byte-order free.
13
13
  # This is based on the Intel's slice-by-eight algorithm.
14
14
  #
15
15
  # It's faster than about 50% (CRC-32) and about 30% (CRC-64) of
@@ -26,69 +26,46 @@
26
26
  #
27
27
  # If defined "RUBY_CRC_NOFAST=3" enviroment variable, switch to reference algorithm.
28
28
  #
29
- module CRC
30
- module Utils
31
- def bitreflect8(n)
32
- n = n.to_i
33
- n = ((n & 0x55) << 1) | ((n >> 1) & 0x55)
34
- n = ((n & 0x33) << 2) | ((n >> 2) & 0x33)
35
- return ((n & 0x0f) << 4) | (n >> 4) # 0x0f
36
- end
37
-
38
- def bitreflect16(n)
39
- n = n.to_i
40
- n = ((n & 0x5555) << 1) | ((n >> 1) & 0x5555)
41
- n = ((n & 0x3333) << 2) | ((n >> 2) & 0x3333)
42
- n = ((n & 0x0f0f) << 4) | ((n >> 4) & 0x0f0f)
43
- return ((n & 0x00ff) << 8) | (n >> 8) # 0x00ff
44
- end
45
-
46
- def bitreflect32(n)
47
- n = n.to_i
48
- n = ((n & 0x55555555) << 1) | ((n >> 1) & 0x55555555)
49
- n = ((n & 0x33333333) << 2) | ((n >> 2) & 0x33333333)
50
- n = ((n & 0x0f0f0f0f) << 4) | ((n >> 4) & 0x0f0f0f0f)
51
- n = ((n & 0x00ff00ff) << 8) | ((n >> 8) & 0x00ff00ff)
52
- return ((n & 0x0000ffff) << 16) | (n >> 16) # 0x0000ffff
53
- end
54
-
55
- def bitreflect64(n)
56
- n = n.to_i
57
- n = ((n & 0x5555555555555555) << 1) | ((n >> 1) & 0x5555555555555555)
58
- n = ((n & 0x3333333333333333) << 2) | ((n >> 2) & 0x3333333333333333)
59
- n = ((n & 0x0f0f0f0f0f0f0f0f) << 4) | ((n >> 4) & 0x0f0f0f0f0f0f0f0f)
60
- n = ((n & 0x00ff00ff00ff00ff) << 8) | ((n >> 8) & 0x00ff00ff00ff00ff)
61
- n = ((n & 0x0000ffff0000ffff) << 16) | ((n >> 16) & 0x0000ffff0000ffff)
62
- return ((n & 0x00000000ffffffff) << 32) | (n >> 32) # 0x00000000ffffffff
63
- end
64
-
65
- def bitreflect128(n)
66
- n = n.to_i
67
- n = ((n & 0x55555555555555555555555555555555) << 1) | ((n >> 1) & 0x55555555555555555555555555555555)
68
- n = ((n & 0x33333333333333333333333333333333) << 2) | ((n >> 2) & 0x33333333333333333333333333333333)
69
- n = ((n & 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f) << 4) | ((n >> 4) & 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f)
70
- n = ((n & 0x00ff00ff00ff00ff00ff00ff00ff00ff) << 8) | ((n >> 8) & 0x00ff00ff00ff00ff00ff00ff00ff00ff)
71
- n = ((n & 0x0000ffff0000ffff0000ffff0000ffff) << 16) | ((n >> 16) & 0x0000ffff0000ffff0000ffff0000ffff)
72
- n = ((n & 0x00000000ffffffff00000000ffffffff) << 32) | ((n >> 32) & 0x00000000ffffffff00000000ffffffff)
73
- return ((n & 0x0000000000000000ffffffffffffffff) << 64) | (n >> 64) # 0x0000000000000000ffffffffffffffff
74
- end
75
- end
76
-
77
- class Generator < Struct.new(:bitsize, :bitmask, :polynomial, :initial_state, :table, :reflect_input, :reflect_output, :xor_output, :name)
78
- BasicStruct = superclass
79
-
80
- def initialize(bitsize, polynomial, initial_state = 0, reflect_input = true, reflect_output = true, xor_output = ~0, name = nil)
29
+ class CRC
30
+ class << self
31
+ #
32
+ # call-seq:
33
+ # new(bitsize, polynomial, initial_crc = 0, reflect_input = true, reflect_output = true, xor_output = ~0, name = nil) -> new crc module class (CRC based class)
34
+ # new(initial_crc = nil, size = 0) -> new crc generator (CRC instance)
35
+ # new(seq, initial_crc = nil, size = 0) -> new crc generator (CRC instance)
36
+ #
37
+ def new(bitsize, polynomial, initial_crc = 0, reflect_input = true, reflect_output = true, xor_output = ~0, name = nil)
81
38
  bitsize = bitsize.to_i
82
39
  if bitsize < 1 || bitsize > 64
83
40
  raise ArgumentError, "wrong bitsize (except 1..64, but given #{bitsize})"
84
41
  end
42
+
85
43
  bitmask = ~(~0 << bitsize)
86
44
  polynomial = bitmask & polynomial
87
- initial_state = bitmask & initial_state
45
+ initial_crc = bitmask & initial_crc
88
46
  xor_output = bitmask & xor_output
89
47
  name = (name.nil? || ((name = String(name)).empty?)) ? nil : name
90
- super(bitsize, bitmask, polynomial, initial_state, nil,
91
- !!reflect_input, !!reflect_output, xor_output, name)
48
+
49
+ ::Class.new(self) do
50
+ @bitsize = bitsize
51
+ @bitmask = bitmask
52
+ @polynomial = polynomial
53
+ @initial_crc = initial_crc
54
+ @table = nil
55
+ @reflect_input = !!reflect_input
56
+ @reflect_output = !!reflect_output
57
+ @xor_output = xor_output
58
+ @name = name
59
+
60
+ # CRC クラスを普通に派生させた場合でも、CRC.new の基底メソッドが呼ばれるための細工
61
+ define_singleton_method(:new, &Class.instance_method(:new).bind(self))
62
+
63
+ singleton_class.class_eval do
64
+ alias_method :[], :new
65
+ end
66
+
67
+ extend CRC::ModuleClass
68
+ end
92
69
  end
93
70
 
94
71
  def update_with_reference(seq, state)
@@ -204,14 +181,14 @@ module CRC
204
181
 
205
182
  def table
206
183
  if reflect_input
207
- set_table t = CRC.build_reflect_table(bitsize, polynomial, slice: 16)
184
+ @table = CRC.build_reflect_table(bitsize, polynomial, slice: 16)
208
185
  else
209
- set_table t = CRC.build_table(bitsize, polynomial, slice: 16)
186
+ @table = CRC.build_table(bitsize, polynomial, slice: 16)
210
187
  end
211
188
 
212
- define_singleton_method :table, self.class.superclass.instance_method(:table)
189
+ singleton_class.class_eval "attr_reader :table"
213
190
 
214
- t
191
+ @table
215
192
  end
216
193
 
217
194
  case ENV["RUBY_CRC_NOFAST"].to_i
@@ -222,13 +199,60 @@ module CRC
222
199
  else
223
200
  alias update update_with_reference
224
201
  end
202
+ end
203
+
204
+ module ModuleClass
205
+ attr_reader :bitsize, :bitmask, :polynomial, :initial_crc,
206
+ :reflect_input, :reflect_output, :xor_output, :name
207
+
208
+ alias reflect_input? reflect_input
209
+ alias reflect_output? reflect_output
210
+ end
211
+
212
+ module Utils
213
+ def bitreflect8(n)
214
+ n = n.to_i
215
+ n = ((n & 0x55) << 1) | ((n >> 1) & 0x55)
216
+ n = ((n & 0x33) << 2) | ((n >> 2) & 0x33)
217
+ return ((n & 0x0f) << 4) | (n >> 4) # 0x0f
218
+ end
225
219
 
226
- class BasicStruct
227
- alias set_table table=
228
- private :set_table
220
+ def bitreflect16(n)
221
+ n = n.to_i
222
+ n = ((n & 0x5555) << 1) | ((n >> 1) & 0x5555)
223
+ n = ((n & 0x3333) << 2) | ((n >> 2) & 0x3333)
224
+ n = ((n & 0x0f0f) << 4) | ((n >> 4) & 0x0f0f)
225
+ return ((n & 0x00ff) << 8) | (n >> 8) # 0x00ff
226
+ end
229
227
 
230
- undef :bitsize=, :bitmask=, :polynomial=, :initial_state=, :table=,
231
- :reflect_input=, :reflect_output=, :xor_output=, :name=, :[]=
228
+ def bitreflect32(n)
229
+ n = n.to_i
230
+ n = ((n & 0x55555555) << 1) | ((n >> 1) & 0x55555555)
231
+ n = ((n & 0x33333333) << 2) | ((n >> 2) & 0x33333333)
232
+ n = ((n & 0x0f0f0f0f) << 4) | ((n >> 4) & 0x0f0f0f0f)
233
+ n = ((n & 0x00ff00ff) << 8) | ((n >> 8) & 0x00ff00ff)
234
+ return ((n & 0x0000ffff) << 16) | (n >> 16) # 0x0000ffff
235
+ end
236
+
237
+ def bitreflect64(n)
238
+ n = n.to_i
239
+ n = ((n & 0x5555555555555555) << 1) | ((n >> 1) & 0x5555555555555555)
240
+ n = ((n & 0x3333333333333333) << 2) | ((n >> 2) & 0x3333333333333333)
241
+ n = ((n & 0x0f0f0f0f0f0f0f0f) << 4) | ((n >> 4) & 0x0f0f0f0f0f0f0f0f)
242
+ n = ((n & 0x00ff00ff00ff00ff) << 8) | ((n >> 8) & 0x00ff00ff00ff00ff)
243
+ n = ((n & 0x0000ffff0000ffff) << 16) | ((n >> 16) & 0x0000ffff0000ffff)
244
+ return ((n & 0x00000000ffffffff) << 32) | (n >> 32) # 0x00000000ffffffff
245
+ end
246
+
247
+ def bitreflect128(n)
248
+ n = n.to_i
249
+ n = ((n & 0x55555555555555555555555555555555) << 1) | ((n >> 1) & 0x55555555555555555555555555555555)
250
+ n = ((n & 0x33333333333333333333333333333333) << 2) | ((n >> 2) & 0x33333333333333333333333333333333)
251
+ n = ((n & 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f) << 4) | ((n >> 4) & 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f)
252
+ n = ((n & 0x00ff00ff00ff00ff00ff00ff00ff00ff) << 8) | ((n >> 8) & 0x00ff00ff00ff00ff00ff00ff00ff00ff)
253
+ n = ((n & 0x0000ffff0000ffff0000ffff0000ffff) << 16) | ((n >> 16) & 0x0000ffff0000ffff0000ffff0000ffff)
254
+ n = ((n & 0x00000000ffffffff00000000ffffffff) << 32) | ((n >> 32) & 0x00000000ffffffff00000000ffffffff)
255
+ return ((n & 0x0000000000000000ffffffffffffffff) << 64) | (n >> 64) # 0x0000000000000000ffffffffffffffff
232
256
  end
233
257
  end
234
258
  end
@@ -33,7 +33,7 @@
33
33
  # License:: zlib-style
34
34
  #--
35
35
 
36
- module CRC
36
+ class CRC
37
37
  module Aux
38
38
  def self.gf2_matrix_times(matrix, vector)
39
39
  sum = 0
@@ -53,13 +53,13 @@ module CRC
53
53
 
54
54
  nil
55
55
  end
56
- end
57
56
 
58
- class Generator
59
- def combine(crc1, crc2, len2)
57
+ def self.combine(crc1, crc2, len2,
58
+ bitsize, polynomial, initial_crc,
59
+ reflect_input, reflect_output, xor_output)
60
60
  return crc1 unless len2 > 1
61
61
 
62
- crc1 ^= initial_state
62
+ crc1 ^= initial_crc
63
63
 
64
64
  odd = []
65
65
  even = []
@@ -12,12 +12,13 @@
12
12
  # * https://github.com/cluelogic/cluelib/blob/master/src/cl_crc.svh
13
13
  # * https://users.ece.cmu.edu/~koopman/crc/hw_data.html
14
14
  # * https://users.ece.cmu.edu/~koopman/roses/dsn04/koopman04_crc_poly_embedded.pdf
15
+ # * (CRC-64-ISO-3309) http://swissknife.cvs.sourceforge.net/viewvc/swissknife/SWISS/lib/SWISS/CRC64.pm
15
16
  #++
16
17
 
17
- module CRC
18
+ class CRC
18
19
  LIST = [
19
20
  #
20
- # bit size, polynomial, initial state,
21
+ # bit size, polynomial, initial crc,
21
22
  # refrect input, xor output,
22
23
  # reflect output, crc("123456789"), names...
23
24
  #
@@ -33,10 +34,10 @@ module CRC
33
34
  [ 6, 0x19, true, true, 0, 0, 0x26, "CRC-6-DARC"],
34
35
  [ 6, 0x03, true, true, 0, 0, 0x06, "CRC-6-ITU"],
35
36
  [ 7, 0x09, false, false, 0, 0, 0x75, "CRC-7", "CRC-7-JESD84-A441"],
36
- [ 7, 0x65, false, false, 0, 0, nil, "CRC-7-MVB"],
37
+ #[ 7, 0x65, false, false, 0, 0, nil, "CRC-7-MVB"],
37
38
  [ 7, 0x4F, true, true, ~0, 0, 0x53, "CRC-7-ROHC", "CRC-7-RFC 3095"],
38
39
  [ 7, 0x45, false, false, 0, 0, 0x61, "CRC-7-UMTS"],
39
- [ 8, 0xD5, false, false, 0, 0, nil, "CRC-8"],
40
+ #[ 8, 0xD5, false, false, 0, 0, nil, "CRC-8"],
40
41
  [ 8, 0x07, false, false, 0, 0, 0xF4, "CRC-8-CCITT", "CRC-8-SMBus"],
41
42
  [ 8, 0x31, true, true, 0, 0, 0xA1, "CRC-8-MAXIM", "CRC-8-Dallas/Maxim", "DOW-CRC"],
42
43
  [ 8, 0x39, true, true, 0, 0, 0x15, "CRC-8-DARC"],
@@ -60,9 +61,9 @@ module CRC
60
61
  [14, 0x0805, true, true, 0, 0, 0x082D, "CRC-14-DARC"],
61
62
  [15, 0x4599, false, false, 0, 0, 0x059E, "CRC-15", "CRC-15-CAN"],
62
63
  [15, 0x6815, false, false, 1, 1, 0x2566, "CRC-15-MPT1327"],
63
- [16, 0x2F15, false, false, 0, 0, nil, "Chakravarty"],
64
- [16, 0x8005, true, true, 0, 0, 0xBB3D, "ARC", "CRC-16", "CRC-IBM", "CRC-16-ARC", "CRC-16-LHA"],
65
- [16, 0xA02B, false, false, 0, 0, nil, "CRC-16-ARINC"],
64
+ #[16, 0x2F15, false, false, 0, 0, nil, "Chakravarty"],
65
+ [16, 0x8005, true, true, 0, 0, 0xBB3D, "CRC-16", "ARC", "CRC-IBM", "CRC-16-ARC", "CRC-16-LHA"],
66
+ #[16, 0xA02B, false, false, 0, 0, nil, "CRC-16-ARINC"],
66
67
  [16, 0x1021, false, false, 0x1D0F, 0, 0xE5CC, "CRC-16-AUG-CCITT", "CRC-16-SPI-FUJITSU"],
67
68
  [16, 0xC867, false, false, ~0, 0, 0x4C06, "CRC-16-CDMA2000"],
68
69
  [16, 0x0589, false, false, 1, 1, 0x007E, "CRC-16-DECT-R", "R-CRC-16"],
@@ -81,14 +82,14 @@ module CRC
81
82
  [16, 0xA097, false, false, 0, 0, 0x0FB3, "CRC-16-TELEDISK"],
82
83
  [16, 0x1021, true, true, 0x89EC, 0, 0x26B1, "CRC-16-TMS37157"],
83
84
  [16, 0x8005, true, true, 0, ~0, 0xB4C8, "CRC-16-USB"],
84
- [16, 0x1021, true, true, 0xC6C6, 0, 0xBF05, "CRC-A", "CRC-16-ISO/IEC FCD 14443-3"],
85
- [16, 0x1021, true, true, 0, 0, 0x2189, "KERMIT", "CRC-16-CCITT", "CRC-16-CCITT-TRUE", "CRC-CCITT"],
86
- [16, 0x8005, true, true, ~0, 0, 0x4B37, "MODBUS"],
87
- [16, 0x1021, true, true, 0, ~0, 0x906E, "X-25", "CRC-16-IBM-SDLC", "CRC-16-ISO-HDLC", "CRC-B"],
88
- [16, 0x1021, false, false, 0, 0, 0x31C3, "XMODEM", "ZMODEM", "CRC-16-ACORN", "CRC-16-LTE"],
89
- [17, 0x0001685B, false, false, 0, 0, nil, "CRC-17-CAN"],
90
- [21, 0x00102899, false, false, 0, 0, nil, "CRC-21-CAN"],
91
- [24, 0x005D6DCB, false, false, 0, 0, nil, "CRC-24"],
85
+ [16, 0x1021, true, true, 0xC6C6, 0, 0xBF05, "CRC-16-A", "CRC-A", "CRC-16-ISO/IEC FCD 14443-3"],
86
+ [16, 0x1021, true, true, 0, 0, 0x2189, "CRC-16-KERMIT", "KERMIT", "CRC-16-CCITT", "CRC-16-CCITT-TRUE", "CRC-CCITT"],
87
+ [16, 0x8005, true, true, ~0, 0, 0x4B37, "CRC-16-MODBUS", "MODBUS"],
88
+ [16, 0x1021, true, true, 0, ~0, 0x906E, "CRC-16-X-25", "X-25", "CRC-16-IBM-SDLC", "CRC-16-ISO-HDLC", "CRC-16-CRC-B", "CRC-B"],
89
+ [16, 0x1021, false, false, 0, 0, 0x31C3, "CRC-16-XMODEM", "XMODEM", "CRC-16-ZMODEM", "ZMODEM", "CRC-16-ACORN", "CRC-16-LTE"],
90
+ #[17, 0x0001685B, false, false, 0, 0, nil, "CRC-17-CAN"],
91
+ #[21, 0x00102899, false, false, 0, 0, nil, "CRC-21-CAN"],
92
+ #[24, 0x005D6DCB, false, false, 0, 0, nil, "CRC-24"],
92
93
  [24, 0x00864CFB, false, false, 0, 0, 0x00CDE703, "CRC-24-Radix-64"],
93
94
  [24, 0x00864CFB, false, false, 0x00B704CE, 0, 0x0021CF02, "CRC-24-OPENPGP"],
94
95
  [24, 0x0000065B, true, true, 0x00555555, 0, 0x00C25A56, "CRC-24-BLE"],
@@ -97,25 +98,25 @@ module CRC
97
98
  [24, 0x00328B63, false, false, 0, ~0, 0x00B4F3E6, "CRC-24-INTERLAKEN"],
98
99
  [24, 0x00864CFB, false, false, 0, 0, 0x00CDE703, "CRC-24-LTE-A"],
99
100
  [24, 0x00800063, false, false, 0, 0, 0x0023EF52, "CRC-24-LTE-B"],
100
- [30, 0x2030B9C7, false, false, 0, 0, nil, "CRC-30"],
101
+ #[30, 0x2030B9C7, false, false, 0, 0, nil, "CRC-30"],
101
102
  [30, 0x2030B9C7, false, false, 0, ~0, 0x04C34ABF, "CRC-30-CDMA"],
102
103
  [31, 0x04C11DB7, false, false, 0, ~0, 0x0CE9E46C, "CRC-31-PHILIPS"],
103
- [32, 0x04C11DB7, true, true, 0, ~0, 0xCBF43926, "CRC-32", "CRC-32-ADCCP", "PKZIP", "CRC-32-PKZIP"],
104
+ [32, 0x04C11DB7, true, true, 0, ~0, 0xCBF43926, "CRC-32", "CRC-32-ADCCP", "CRC-32-PKZIP", "PKZIP"],
104
105
  [32, 0x04C11DB7, false, false, 0, ~0, 0xFC891918, "CRC-32-BZIP2", "CRC-32-AAL5", "CRC-32-DECT-B", "B-CRC-32"],
105
106
  [32, 0x1EDC6F41, true, true, 0, ~0, 0xE3069283, "CRC-32C", "CRC-32-ISCSI", "CRC-32-CASTAGNOLI", "CRC-32-INTERLAKEN"],
106
107
  [32, 0xa833982b, true, true, 0, ~0, 0x87315576, "CRC-32D"],
107
108
  [32, 0x04C11DB7, false, false, ~0, 0, 0x0376E6E7, "CRC-32-MPEG-2"],
108
109
  [32, 0x04C11DB7, false, false, ~0, ~0, 0x765E7680, "CRC-32-POSIX", "CKSUM"],
109
- [32, 0x741B8CD7, true, true, 0, ~0, nil, "CRC-32K"],
110
- [32, 0x32583499, true, true, 0, ~0, nil, "CRC-32K2"],
110
+ #[32, 0x741B8CD7, true, true, 0, ~0, nil, "CRC-32K"],
111
+ #[32, 0x32583499, true, true, 0, ~0, nil, "CRC-32K2"],
111
112
  [32, 0x814141AB, false, false, 0, 0, 0x3010BF7F, "CRC-32Q"],
112
- [32, 0x04C11DB7, true, true, ~0, 0, 0x340BC6D9, "JAMCRC", "CRC-32-JAMCRC"],
113
- [32, 0x000000AF, false, false, 0, 0, 0xBD0BE338, "XFER", "CRC-32-XFER"],
113
+ [32, 0x04C11DB7, true, true, ~0, 0, 0x340BC6D9, "CRC-32-JAMCRC", "JAMCRC"],
114
+ [32, 0x000000AF, false, false, 0, 0, 0xBD0BE338, "CRC-32-XFER", "XFER"],
114
115
  [40, 0x0004820009, false, false, ~0, ~0, 0xD4164FC646, "CRC-40-GSM"],
115
- [64, 0x42F0E1EBA9EA3693, true, true, 0, ~0, 0x995DC9BBDF1939FA, "CRC-64", "CRC-64-XZ"],
116
+ [64, 0x42F0E1EBA9EA3693, true, true, 0, ~0, 0x995DC9BBDF1939FA, "CRC-64-XZ", "CRC-64"],
116
117
  [64, 0x42F0E1EBA9EA3693, false, false, 0, 0, 0x6C40DF5F0B497347, "CRC-64-ECMA", "CRC-64-ECMA-182"],
117
118
  [64, 0x42F0E1EBA9EA3693, false, false, 0, ~0, 0x62EC59E3F1A4F00A, "CRC-64-WE"],
118
- [64, 0x000000000000001B, false, false, 0, 0, nil, "CRC-64-ISO"],
119
+ [64, 0x000000000000001B, true, true, 0, 0, 0x46A5A9388A5BEFFE, "CRC-64-ISO", "CRC-64-ISO-3309"],
119
120
  # [82, 0x308C0111011401440411, true, true, 0, 0, 0x9EA83F625023801FD612, "CRC-82/DARC"],
120
121
  ]
121
122
  end
@@ -0,0 +1,195 @@
1
+ #!ruby
2
+
3
+ require_relative "../crc"
4
+
5
+ class CRC
6
+ module ModuleClass
7
+ #
8
+ # call-seq:
9
+ # acrc(crc, rest_seq = nil, target_crc = 0) -> byte string as arc-code
10
+ #
11
+ # 目的となる crc になるように、指定された crc に続くバイト列を逆算します。
12
+ #
13
+ # 出力されるバイト列は、crc のビット数を表現できるバイト数となります。
14
+ #
15
+ # 現在のところ、reflect-input/output 限定となっています。
16
+ #
17
+ # * crc32("123456789????") の結果が 0 となるような、???? の部分を逆算する
18
+ #
19
+ # seq = "123456789"
20
+ # seq << CRC::CRC32.acrc(seq)
21
+ # p CRC::CRC32[seq] # => #<CRC::CRC32:00000000>
22
+ #
23
+ # * crc32("123456789????ABCDEFG") の結果が 0 となるような、???? の部分を逆算する
24
+ #
25
+ # seq1 = "123456789"
26
+ # seq2 = "ABCDEFG"
27
+ # seq = seq1 + CRC::CRC32.acrc(seq1, seq2) + seq2
28
+ # p CRC::CRC32[seq] # => #<CRC::CRC32:00000000>
29
+ #
30
+ # * crc32("123456789????ABCDEFG") の結果が 0x12345678 となるような、???? の部分を逆算する
31
+ #
32
+ # seq1 = "123456789"
33
+ # seq2 = "ABCDEFG"
34
+ # target_crc = 0x12345678
35
+ # seq = seq1 + CRC::CRC32.acrc(seq1, seq2, target_crc) + seq2
36
+ # p CRC::CRC32[seq] # => #<CRC::CRC32:12345678>
37
+ #
38
+ def acrc(crc, rest_seq = nil, target_crc = 0)
39
+ raise NotImplementedError, "crc polynomial is not odd" unless polynomial.odd?
40
+ raise NotImplementedError, "crc module is not reflect input and output" unless reflect_input? && reflect_output?
41
+
42
+ bitsize = self.bitsize
43
+ poly = CRC.bitreflect(polynomial, bitsize)
44
+ target_crc = target_crc.to_i
45
+ target_crc ^= xor_output
46
+
47
+ if rest_seq
48
+ rest_seq.bytesize.downto(1) do |i|
49
+ target_crc = Aux.acrc_loop_reflect(target_crc, rest_seq.getbyte(i - 1), poly, bitsize, 0xff, 8)
50
+ end
51
+ end
52
+
53
+ bytes = (bitsize + 7) / 8
54
+ bits = bytes * 8
55
+
56
+ case crc
57
+ when Numeric
58
+ state = bitmask & crc ^ xor_output
59
+ when CRC
60
+ raise "different crc module (given %p(%p), expect %p)" % [crc, crc.class, self] unless variant?(crc)
61
+ state = crc.state
62
+ else
63
+ state = new(crc).state
64
+ end
65
+
66
+ if bits > bitsize
67
+ # ビット数が 8 の境界にない場合、その隙間分を埋める。
68
+ # 現在の実装では、最終結果のバイト列における最終バイト値の
69
+ # 上位ビットが 0 であるようにしている。
70
+ pad = bits - bitsize
71
+ target_crc = Aux.acrc_loop_reflect(target_crc, 0, poly, bitsize, 0xff, pad)
72
+ end
73
+
74
+ target_crc = Aux.acrc_loop_reflect(target_crc, state, poly, bitsize, bitmask, bitsize)
75
+
76
+ bytes.times.reduce("") { |a, *| a << (target_crc & 0xff).chr(Encoding::BINARY); target_crc >>= 8; a }
77
+ end
78
+ end
79
+
80
+ module Aux
81
+ def self.acrc_loop_reflect(target_crc, state, poly, crcbits, bitmask, bits)
82
+ head = bits - 1
83
+ bitmask1 = bitmask >> 1
84
+ crchead = crcbits - 1
85
+
86
+ #puts "target_crc=0b%016b, state=0b%016b, reversed-polynomial=0b%016b" % [target_crc, state, poly]
87
+ bits.times do |i|
88
+ if target_crc[crchead] == 0
89
+ target_crc <<= 1
90
+ else
91
+ target_crc ^= poly
92
+ target_crc <<= 1
93
+ target_crc |= 0x01
94
+ end
95
+
96
+ target_crc ^= state[head]
97
+ #puts " 0_%016b ^ %d" % [target_crc, state[head]]
98
+ state = (state & bitmask1) << 1
99
+ end
100
+ #puts "target_crc=0b%016b" % target_crc
101
+
102
+ target_crc
103
+ end
104
+ end
105
+ end
106
+
107
+ if $0 == __FILE__
108
+ seq = "abcdefghijklmnopqrstuvwxyz"
109
+ seq2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
110
+ code = CRC::X_25.acrc(seq, seq2)
111
+ puts "base-crc=[%p, %p], arc'd-crc=%p, arc-code=%s" % [CRC::X_25[seq], CRC::X_25[seq2], CRC::X_25[seq + code + seq2], code.unpack("H*")[0]]
112
+ code = CRC::CRC32.acrc(seq, seq2)
113
+ puts "base-crc=[%p, %p], arc'd-crc=%p, arc-code=%s" % [CRC::CRC32[seq], CRC::CRC32[seq2], CRC::CRC32[seq + code + seq2], code.unpack("H*")[0]]
114
+ code = CRC::CRC32C.acrc(seq, seq2)
115
+ puts "base-crc=[%p, %p], arc'd-crc=%p, arc-code=%s" % [CRC::CRC32C[seq], CRC::CRC32C[seq2], CRC::CRC32C[seq + code + seq2], code.unpack("H*")[0]]
116
+
117
+ MyCRC = crcmod = CRC.new(32, rand(1<<32) | 1, rand(1<<32) | 1, true, true, rand(1<<32) | 1)
118
+ 20.times do |i|
119
+ s = (10+rand(20)).times.reduce("") { |a, *| a << rand(256).chr(Encoding::BINARY) }
120
+ t = (10+rand(20)).times.reduce("") { |a, *| a << rand(256).chr(Encoding::BINARY) }
121
+ crc = crcmod.new(s)
122
+ puts "crc=[%p, %p], arc'd-crc=%p, target=%08X, seq=%s" %
123
+ [crc, crcmod[t], crcmod.new(s + crcmod.acrc(crc.crc, t, i * 9929) + t), i * 9929, s.unpack("H*")[0]]
124
+ end
125
+ end
126
+
127
+ __END__
128
+
129
+ 目的となる CRC 値を逆算して、特定のバイト列を得る機能です。
130
+
131
+ ただの思いつきで、crc すると結果が 0 になるバイト列を計算できないかなと遊んでみた結果、
132
+ それなりの形となってしまいました。
133
+
134
+ 以下は acrc メソッドとして実装した、その仕組みとなります。
135
+
136
+
137
+ X-25{CRC-16-0x1021 ref-in/out xor=0xffff} を用いた場合
138
+
139
+ ("abcdefghijklmnopqrstuvwxyz" + ??) を CRC して結果を 0 にしたい (?? は2バイト)。
140
+
141
+ この時の ?? を求める。
142
+
143
+ 先に "abcdefghijklmnopqrstuvwxyz" までの CRC を求めておく => 0x0d43
144
+
145
+ (ここまでの内部状態は 0xf2bc) ?? <STOP> (この段階で内部状態が 0xffff であること)
146
+
147
+ 内部状態の最上位ビットから順に送って、目的となる内部状態が 0xffff から 0xf2bc になるような値を逆算する
148
+
149
+
150
+ code = 0 # 最終的に求めたい CRC
151
+ state = 0b1111001010111100 # 現在の CRC 生成器の内部状態
152
+ reversed_polynomial = 0b1000010000001000
153
+
154
+ 1. 最終的に求めたい CRC と xor_output する
155
+ 1111111111111111
156
+
157
+ 2. この時、code の最上位ビットが1なので、poly (reversed) で xor する
158
+ 最上位ビットが0ならば何もしない
159
+ 0111101111110111
160
+
161
+ 3. 左にずらす
162
+ 1111011111101110
163
+
164
+ 4. (2) において poly-reversed で xor したため、最下位ビットを1にする
165
+ (2) を行わなかった場合は何もしない
166
+ 1111011111101111
167
+
168
+ 5. 目的となる内部状態の最上位ビットと作業内部状態の最下位ビットを xor した時に 1 となるように調整する
169
+ (2) を行わなかった場合は 0 を維持するように処置する
170
+ 1111011111101110
171
+
172
+ 6. 1 ビット目の処理が完了。(2) に戻って必要なだけ繰り返す
173
+
174
+ 1111011111101110 <= 1 ## 最上位から2ビット目を入力
175
+ 1110011111001100 <= 1 ## 最上位から3ビット目を入力
176
+ 1100011110001000 <= 1 ## 以下同様に……
177
+ 1000011100000000 <= 0
178
+ 0000011000010001 <= 0
179
+ 0000110000100010 <= 1
180
+ 0001100001000101 <= 0
181
+ 0011000010001010 <= 1
182
+ 0110000100010101 <= 0
183
+ 1100001000101010 <= 1
184
+ 1000110001000100 <= 1
185
+ 0001000010011000 <= 1
186
+ 0010000100110001 <= 1
187
+ 0100001001100011 <= 0
188
+ 1000010011000110 <= 0
189
+ 0000000110011101 ## 繰り返して得られた結果
190
+ この結果を元にして、バイト順を入れ替える
191
+ (CRC として求める場合に、下位から入力されるため)
192
+
193
+ 10011101:00000001 >>>> [0x9d, 0x01] が返る
194
+
195
+ [EOF]