finitefield 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.txt CHANGED
@@ -8,4 +8,9 @@ supported.
8
8
  The initial release of this library is limited in scope to only supporting
9
9
  fields of the form 2^n.
10
10
 
11
-
11
+ Examples illustrating how to use the field are given in the examples directory.
12
+ Currently the following examples are provided:
13
+ * logTables.rb:
14
+ - log and antilog table generation given a field polynomial and generator.
15
+ * raid6.rb:
16
+ - RAID6 Q block generation using finite fields.
@@ -0,0 +1,16 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
2
+
3
+ # = exampleUtils.rb - Utility methods used by the other examples.
4
+ #
5
+ # Copyright (C) 2008 Stephen Doyle
6
+ #
7
+
8
+ # Utility method to print a nicely formatted 16xn table of hex values
9
+ def printTable(table)
10
+ (0...table.length).each do |i|
11
+ printf("%02x ", table[i])
12
+ if i!=0 and i%16==15
13
+ puts ''
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,88 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
2
+
3
+ # = logTables.rb - Generate the anti-log and log tables for a finite field.
4
+ #
5
+ # Copyright (C) 2008 Stephen Doyle
6
+ #
7
+ # This example illustrates using the finitefield library to generate the
8
+ # anti-log and log tables for a finite field for a given field polynomial
9
+ # and generator.
10
+ #
11
+ # The anti-log table for a finite field is constructed using a generator
12
+ # whose successive powers g^n for the range n[0, 255] produce all the
13
+ # in the field without repeating any element.
14
+ #
15
+ # If the anti-log and log tables are available for a finite field,
16
+ # multiplication can be performed very quickly using these tables, e.g.
17
+ # mult(a, b) = anti_log( [log(a) + log(b)] % 0xFF )
18
+ # where + is normal addition, i.e. not addition within the finite field.
19
+ #
20
+
21
+ require 'finitefield'
22
+ require 'exampleUtils'
23
+
24
+ # Compute the inverse or anti log table for a given field polynomial and generator.
25
+ # Note that the last value of the ilogTable is invalid and present in this example
26
+ # as a placeholder to produce a nicely dimensioned array.
27
+ def getILogTable(poly, generator)
28
+ field = FiniteField.new(8, poly)
29
+ ilogTable = [1]
30
+
31
+ 1.upto(0xFF) do |i|
32
+ ilogTable[i] = field.multiply(ilogTable[i-1], generator)
33
+ end
34
+ return ilogTable
35
+ end
36
+
37
+ # Compute the log log table for a given field polynomial and generator.
38
+ def getLogTable(poly, generator)
39
+ # The log table is most easily generated from the inverse log table.
40
+ # Note that the last element in the inverse log table is invalid and so
41
+ # should be discarded to avoid introducing errors into the log table
42
+ # generation.
43
+ ilogTable = getILogTable(poly, generator)[0...-1]
44
+ tmp = {}
45
+ ilogTable.each_with_index { |value, index| tmp[value] = index }
46
+ logTable = [0] + tmp.sort.collect { |x| x[1]}
47
+ return logTable
48
+ end
49
+
50
+
51
+ # Generate and print the anti-log and log tables for two well known fields ...
52
+ # ... the 0x11D field is the default polynomial used for the GF(2^8)
53
+ # computations used in RAID 6 for the generation of the Q parity block.
54
+ puts "Inverse log table for polynomial 0x11D: "
55
+ ilogTable = getILogTable(0x11D, 2)
56
+ printTable(ilogTable)
57
+ puts ''
58
+
59
+ puts "Log table for polynomial 0x11D: "
60
+ logTable = getLogTable(0x11D, 2)
61
+ printTable(logTable)
62
+ puts ''
63
+
64
+ # ... the 0x11B polynomial is the polynomial used in AES computations.
65
+ # See: http://www.cs.utsa.edu/~wagner/laws/FFM.html for further details.
66
+ puts "Inverse log table for polynomial 0x11b:"
67
+ ilogTable = getILogTable(0x11b, 3)
68
+ printTable(ilogTable)
69
+ puts ''
70
+
71
+ puts "Log table for polynomial 0x11b: "
72
+ logTable = getLogTable(0x11b, 3)
73
+ printTable(logTable)
74
+ puts ''
75
+
76
+ # Demonstrate multiplication using the tables.
77
+ a = 0x12
78
+ b = 0x34
79
+
80
+ field = FiniteField.new(8, 0x11D)
81
+ r1 = field.multiply(a, b)
82
+
83
+ ilogTable = getILogTable(0x11D, 2)
84
+ logTable = getLogTable(0x11D, 2)
85
+ r2 = ilogTable[ (logTable[a] + logTable[b]) % 0xFF ]
86
+
87
+ puts "Result using FiniteField.multiply(): #{r1}"
88
+ puts "Result using log tables: #{r2}"
data/examples/raid6.rb ADDED
@@ -0,0 +1,82 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
2
+
3
+ # = raid6.rb - Generate the Q parity block for a RAID 6 array.
4
+ #
5
+ # Copyright (C) 2008 Stephen Doyle
6
+ #
7
+ # This example illustrates using the finitefield library in the context
8
+ # of RAID 6 to generate the Q parity block.
9
+ #
10
+ # == Background
11
+ # RAID 6 provides protection against double disk failures in an array of
12
+ # disks by using two disks in the array to hold parity information. The
13
+ # first parity block is known as the P block and generated by taking an
14
+ # XOR of the data blocks in the disk array (D0 + D1 + ... Dn). This is
15
+ # equivalent to addition over a finite field of the form F(2^8).
16
+ #
17
+ # The second parity block, aka the Q block, in a RAID 6 array is generated
18
+ # by multiplying each byte of the data blocks with a coefficient which is
19
+ # slected based upon the position of that disk in the array. The
20
+ # multiplication here is multiplication over a finite field of the form
21
+ # F(2^8) and the coefficients are taken from the anti-log table from the
22
+ # same field. The default RAID 6 polynimial is 0x11D.
23
+ #
24
+ # == What's covered in the example?
25
+ # This example illustrates the computation of both the P and Q blocks for
26
+ # a sample RAID 6 array using a stripe size of 512 bytes.
27
+ #
28
+
29
+ require 'finitefield'
30
+ require 'exampleUtils'
31
+
32
+ class Raid6
33
+
34
+ # Create a field of GF(2^n) using the specified generator polynomial
35
+ def initialize(polynomial)
36
+ @field = FiniteField.new(8, polynomial)
37
+ end
38
+
39
+ def getPBlock(dataBlocks)
40
+ pBlock = [0] * dataBlocks[0].length
41
+ dataBlocks.each do |blk|
42
+ (0...blk.length).each { |byteIdx| pBlock[byteIdx] ^= blk[byteIdx] }
43
+ end
44
+ return pBlock
45
+ end
46
+
47
+ def getQBlock(dataBlocks, coefficients)
48
+ qBlock = [0] * dataBlocks[0].length
49
+ dataBlocks.each_with_index do |blk, blkIdx|
50
+ (0...blk.length).each do |byteIdx|
51
+ qBlock[byteIdx] ^= @field.multiply(blk[byteIdx], coefficients[blkIdx])
52
+ end
53
+ end
54
+ return qBlock
55
+ end
56
+ end
57
+
58
+ # See logTables.rb for futher details.
59
+ def getILogTable(poly, generator)
60
+ field = FiniteField.new(8, poly)
61
+ ilogTable = [1]
62
+
63
+ 1.upto(0xFF) do |i|
64
+ ilogTable[i] = field.multiply(ilogTable[i-1], generator)
65
+ end
66
+ return ilogTable
67
+ end
68
+
69
+ # Sample data
70
+ data = []
71
+ data[0] = [1]*512
72
+ data[1] = [2]*512
73
+ data[2] = [4]*512
74
+ data[3] = [5]*512
75
+ data[4] = [6]*512
76
+ data[5] = [9]*512
77
+
78
+ # Generate the blocks
79
+ raid = Raid6.new(0x11d)
80
+ coefficients = getILogTable(0x11d, 2)
81
+ pBlk = raid.getPBlock(data)
82
+ qBlk = raid.getQBlock(data, coefficients)
data/lib/finitefield.rb CHANGED
@@ -1,9 +1,38 @@
1
-
2
- # Finite fields of characteristic 2
1
+ # = finitefield.rb - Finite Field Arithmetic
2
+ #
3
+ # Copyright (C) 2008 Stephen Doyle
4
+ #
5
+ # == Features
6
+ # finitefield.rb currently supports arithmetic in finite fields of characteristic 2.
7
+ #
8
+ # The following operations are supported:
9
+ # * Addition
10
+ # * Subtraction
11
+ # * Multiplication
12
+ # * Division
13
+ # * Inverse
14
+ # * Reduction
15
+ # * Binary multiplication
16
+ # * Binary division
17
+ #
18
+ # == Example
19
+ #
20
+ # # Create a field
21
+ # field = FiniteField.new(8, 0x169) # <== F(2^8) with polynomial: 0x169
22
+ # # Addition
23
+ # result = field.add(7, 8)
24
+ # # Subtraction
25
+ # result = field.subtract(8, 5)
26
+ # # Multiplication
27
+ # result = field.multiply(9, 87)
28
+ # # Division
29
+ # result = field.divide(87, 9) # <== result = 87/9
30
+ # # Inverse
31
+ # result = field.inverse(31)
32
+ #
3
33
 
4
34
  class FiniteField
5
35
  attr_reader :polynomial
6
- attr_reader :p
7
36
 
8
37
  # Create a field of GF(2^n) using the specified generator polynomial
9
38
  def initialize(n, polynomial)
@@ -50,7 +79,7 @@ class FiniteField
50
79
  return result
51
80
  end
52
81
 
53
- # Reduce the input value by modulo with the generator polynomial
82
+ # Reduce the input value by modulo with the generator polynomial, i.e. result = a % polynomial.
54
83
  def reduce(a)
55
84
  result = 0
56
85
  i = degree(a)
@@ -80,28 +109,27 @@ class FiniteField
80
109
  auxillary[2] = 1
81
110
  i = 2
82
111
 
83
- # puts "#{remainder[i].to_s(base=16)} #{quotient[i].to_s(base=16)} #{auxillary[i].to_s(base=16)}"
84
-
85
112
  while(remainder[i] > 1)
86
113
  i += 1
87
114
  result = binary_div(remainder[i-2], remainder[i-1])
88
115
  remainder[i] = result[1]
89
116
  quotient[i] = result[0]
90
117
  auxillary[i] = binary_mul(quotient[i], auxillary[i-1]) ^ auxillary[i-2]
91
- # puts "#{remainder[i].to_s(base=16)} #{quotient[i].to_s(base=16)} #{auxillary[i].to_s(base=16)}"
92
118
  end
93
119
 
94
120
  return auxillary[i]
95
121
  end
96
122
 
97
- # Division of two field elements (rhs/lhs). This is the same as
98
- # rhs * lhs^-1 i.e. multiply(rhs, inverse(lhs))
123
+ # Division of two field elements (lhs/rhs). This is the same as
124
+ # lhs * rhs^-1 i.e. multiply(lhs, inverse(rhs))
99
125
  def divide(lhs, rhs)
100
126
  multiply(lhs, inverse(rhs))
101
127
  end
102
128
 
103
129
  # Find the degree of the polynomial representing the input field
104
130
  # element v. This takes O(degree(v)) operations.
131
+ #
132
+ # Example: degree(0x141) = 8 ==> 0x141 = x^8 + x^6 + 1
105
133
  def degree(v)
106
134
  if v != 0
107
135
  result = -1
@@ -114,7 +142,7 @@ class FiniteField
114
142
  return 0
115
143
  end
116
144
 
117
- # Binary multiplication. Or more explicitly - multiplication over a binary field
145
+ # Binary multiplication. Or more explicitly - multiplication over a binary field.
118
146
  def binary_mul(lhs, rhs)
119
147
  result = 0
120
148
  a = [degree(lhs), degree(rhs)].max
@@ -127,7 +155,7 @@ class FiniteField
127
155
  return result
128
156
  end
129
157
 
130
- # Binary division. Or more explicitly - division over a binary field
158
+ # Binary division. Or more explicitly - division over a binary field.
131
159
  def binary_div(lhs, rhs)
132
160
  q = 0
133
161
  r = lhs
@@ -145,3 +173,4 @@ class FiniteField
145
173
  end
146
174
 
147
175
  end
176
+
data/test/tc_basic.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
2
2
 
3
+ # Copyright (C) 2008 Stephen Doyle
4
+
3
5
  require 'test/unit'
4
6
  require 'finitefield'
5
7
 
data/test/tc_gf2.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
2
2
 
3
+ # Copyright (C) 2008 Stephen Doyle
4
+
3
5
  require 'test/unit'
4
6
  require 'finitefield'
5
7
 
@@ -1,5 +1,7 @@
1
1
  $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
2
2
 
3
+ # Copyright (C) 2008 Stephen Doyle
4
+
3
5
  require 'test/unit'
4
6
  require 'tc_basic'
5
7
  require 'tc_gf2'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: finitefield
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stephen Doyle
@@ -9,12 +9,12 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-10-24 00:00:00 +01:00
12
+ date: 2008-12-22 00:00:00 +00:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
16
16
  description: Finite Field implementation in Ruby.
17
- email: stephendoyle75@gmail.com
17
+ email:
18
18
  executables: []
19
19
 
20
20
  extensions: []
@@ -28,13 +28,18 @@ files:
28
28
  - test/ts_finitefield.rb
29
29
  - test/tc_basic.rb
30
30
  - test/tc_gf2.rb
31
- has_rdoc: false
31
+ - examples/exampleUtils.rb
32
+ - examples/logTables.rb
33
+ - examples/raid6.rb
34
+ has_rdoc: true
32
35
  homepage: http://finitefield.rubyforge.org/
33
36
  post_install_message:
34
- rdoc_options: []
35
-
37
+ rdoc_options:
38
+ - --title
39
+ - FiniteField Documentation
36
40
  require_paths:
37
41
  - lib
42
+ - lib
38
43
  required_ruby_version: !ruby/object:Gem::Requirement
39
44
  requirements:
40
45
  - - ">="
@@ -49,10 +54,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
49
54
  version:
50
55
  requirements: []
51
56
 
52
- rubyforge_project:
57
+ rubyforge_project: finitefield
53
58
  rubygems_version: 1.0.1
54
59
  signing_key:
55
60
  specification_version: 2
56
61
  summary: Finite Field implementation in Ruby.
57
- test_files: []
58
-
62
+ test_files:
63
+ - test/ts_finitefield.rb