twofish 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. data/LICENSE +27 -0
  2. data/README.rdoc +130 -0
  3. data/Rakefile +35 -0
  4. data/lib/twofish.rb +1177 -0
  5. data/test/test_twofish.rb +290 -0
  6. metadata +61 -0
data/LICENSE ADDED
@@ -0,0 +1,27 @@
1
+
2
+ Copyright 2009 Martin Carpenter. All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without modification, are
5
+ permitted provided that the following conditions are met:
6
+
7
+ 1. Redistributions of source code must retain the above copyright notice, this list of
8
+ conditions and the following disclaimer.
9
+
10
+ 2. Redistributions in binary form must reproduce the above copyright notice, this list
11
+ of conditions and the following disclaimer in the documentation and/or other materials
12
+ provided with the distribution.
13
+
14
+ THIS SOFTWARE IS PROVIDED BY Martin Carpenter ``AS IS'' AND ANY EXPRESS OR IMPLIED
15
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Martin Carpenter OR
17
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
+
24
+ The views and conclusions contained in the software and documentation are those of the
25
+ authors and should not be interpreted as representing official policies, either expressed
26
+ or implied, of Martin Carpenter.
27
+
data/README.rdoc ADDED
@@ -0,0 +1,130 @@
1
+
2
+ = twofish.rb
3
+
4
+ Author:: Martin Carpenter
5
+ Email:: mcarpenter@free.fr
6
+ Copyright:: Copyright (c) Martin Carpenter 2009
7
+
8
+ This class implements the Twofish symmetric encryption algorithm
9
+ in pure Ruby. The original paper describing the cipher "Twofish:
10
+ A 128-Bit Block Cipher" (Schneier, Kelsey, Whiting, Wagner, Hall,
11
+ Ferguson) and further information on Twofish can be found at
12
+ http://www.schneier.com/twofish.html.
13
+
14
+ This implementation is derived with kind permission
15
+ from Guido Flohr's "pure Perl" module Crypt-Twofish_PP:
16
+ http://search.cpan.org/~guido/Crypt-Twofish_PP-0.17. The overall
17
+ structure and a good number of the comments from that implementation
18
+ have been retained.
19
+
20
+
21
+ === Example
22
+
23
+ ECB mode:
24
+
25
+ require 'twofish'
26
+
27
+ key = '1234567890123456'
28
+ tf = Twofish.new(key, :padding => :zero_byte)
29
+ ciphertext = tf.encrypt('Lorem ipsum dolor sit amet')
30
+
31
+ CBC mode with manually specified initialization vector (may alternatively
32
+ be specified in constructor options hash):
33
+
34
+ require 'twofish'
35
+
36
+ key = '1234567890123456'
37
+ tf = Twofish.new(key, :mode => :cbc, :padding => :zero_byte)
38
+ tf.iv = 'abcdefghijklmnop'
39
+ ciphertext = tf.encrypt('Lorem ipsum dolor sit amet')
40
+
41
+
42
+ === Unit tests
43
+
44
+ test_twofish.rb defines the unit tests. The iterative test vectors
45
+ from the original paper are used (although only the final result is
46
+ checked). The CBC mode test vectors were checked using the BouncyCastle
47
+ implementation with JRuby as follows:
48
+
49
+
50
+ include Java
51
+
52
+ require 'bcprov-jdk16-145.jar'
53
+
54
+ include_class Java::org.bouncycastle.jce.provider.BouncyCastleProvider
55
+ include_class Java::org.bouncycastle.crypto.modes.CBCBlockCipher
56
+ include_class Java::org.bouncycastle.crypto.engines.TwofishEngine
57
+ include_class Java::org.bouncycastle.crypto.params.KeyParameter
58
+ include_class Java::org.bouncycastle.crypto.params.ParametersWithIV
59
+
60
+ plaintext = ("\0"*32).to_java_bytes
61
+ ciphertext = ("\0"*32).to_java_bytes
62
+ key = ("\0"*16).to_java_bytes
63
+ iv = ("\0"*16).to_java_bytes
64
+ key_parameter = KeyParameter.new(key)
65
+ cipher_parameter = ParametersWithIV.new(key_parameter, iv)
66
+ cipher = CBCBlockCipher.new TwofishEngine.new
67
+ cipher.init(true, cipher_parameter) # true == encrypt
68
+
69
+ len = 0
70
+ while len < plaintext.length
71
+ len += cipher.processBlock(plaintext, len, ciphertext, len)
72
+ end
73
+
74
+ puts ciphertext.to_a.pack('c*').unpack('H*')
75
+
76
+ The original block test vectors are available as a
77
+ machine-readable file from http://www.schneier.com/code/ecb_ival.txt
78
+
79
+ To run the unit tests, type:
80
+
81
+ rake test
82
+
83
+
84
+ === Documentation
85
+
86
+ Aside from this README, rdoc documentation may be built as follows:
87
+
88
+ rake rdoc
89
+
90
+ The documentation will be built in the rdoc subdirectory.
91
+
92
+
93
+ === Bugs, omissions and weaknesses
94
+
95
+ Encryption and decryption are (not unexpectedly) slow. If you need a
96
+ faster implementation for Ruby then the BouncyCastle provider
97
+ (http://www.bouncycastle.org) plays well with JRuby (http://www.jruby.org).
98
+ See above ("Unit tests") for a sample script.
99
+
100
+ The original "pure Perl" implementation used Perl's integer pragma.
101
+ This implementation uses a private method mask32 to strip off any high
102
+ order bits in an effort to prevent (slow) promotion of Fixnums to Bignums.
103
+ This is a little clumsy and probably could be quicker.
104
+
105
+ Ruby >=1.9 introduces string encodings. The current workaround uses
106
+ #ord and #chr but this is not very satisfactory: it would be preferable
107
+ to move to byte arrays throughout.
108
+
109
+ The only padding mechanisms implemented are "none" (don't pad) and "zero
110
+ byte" (append zero bytes to make up a full block). Zero byte padding has
111
+ a well-known failure mode: if the plaintext terminates in null bytes
112
+ then these may be erroneously removed when un-padding is performed.
113
+
114
+ If no initialization vector is provided for CBC mode then the system
115
+ random number generator (Kernel#rand) is used to generate one. The system
116
+ random number generator may be weaker than desired.
117
+
118
+ The IV is not silently prepended to the ciphertext since if
119
+ the resulting ciphertext is transmitted as is this can introduce
120
+ a weakness. IV should ideally be transmitted OOB. There
121
+ is a good explanation of this risk at Terry Ritter's page
122
+ http://www.ciphersbyritter.com/GLOSSARY.HTM#CipherBlockChaining
123
+
124
+ if the IV is not enciphered, and if the opponents
125
+ can intercept and change the IV in transit, they can
126
+ change the first-block plaintext bit-for-bit, without
127
+ a block-wide garble. That means an opponent could make
128
+ systematic changes to the first block plaintext simply
129
+ by changing the IV.
130
+
data/Rakefile ADDED
@@ -0,0 +1,35 @@
1
+
2
+ require 'rake'
3
+ require 'rake/clean'
4
+ require 'rake/gempackagetask'
5
+ require 'rake/rdoctask'
6
+ require 'rake/testtask'
7
+
8
+ desc 'Default task (test)'
9
+ task :default => [:test]
10
+
11
+ Rake::TestTask.new('test') do |test|
12
+ test.pattern = 'test/*.rb'
13
+ test.warning = true
14
+ end
15
+
16
+ SPECFILE = 'twofish.gemspec'
17
+ if File.exist?(SPECFILE)
18
+ spec = eval( File.read(SPECFILE) )
19
+ Rake::GemPackageTask.new(spec) do |pkg|
20
+ pkg.need_tar = true
21
+ end
22
+ end
23
+
24
+ Rake::RDocTask.new do |rdoc|
25
+ rdoc.rdoc_dir = 'rdoc'
26
+ rdoc.title = 'twofish.rb'
27
+ rdoc.options << '--line-numbers' << '--inline-source'
28
+ rdoc.options << '-A cattr_accessor=object'
29
+ rdoc.options << '--charset' << 'utf-8'
30
+ rdoc.options << '--all'
31
+ rdoc.rdoc_files.include('README.rdoc')
32
+ rdoc.rdoc_files.include('lib/twofish.rb')
33
+ rdoc.rdoc_files.include('test/test_twofish.rb')
34
+ end
35
+
data/lib/twofish.rb ADDED
@@ -0,0 +1,1177 @@
1
+ # twofish.rb
2
+ #
3
+ # Author:: Martin Carpenter
4
+ # Email:: mcarpenter@free.fr
5
+ # Copyright:: Copyright (c) Martin Carpenter 2009
6
+ #
7
+ # Implements a class for symmetric encryption using the Twofish
8
+ # encryption algorithm based on original work by Guido Flohr.
9
+ class Twofish
10
+
11
+ attr_reader :iv, :key_size, :mode, :padding # setters for iv, mode defined below for validation
12
+
13
+ BLOCK_SIZE = 16 # 16 bytes, 128 bits
14
+
15
+ #:stopdoc:
16
+ Q0 = [
17
+ 169, 103, 179, 232, 4, 253, 163, 118, 154, 146, 128, 120, 228,
18
+ 221, 209, 56, 13, 198, 53, 152, 24, 247, 236, 108, 67, 117,
19
+ 55, 38, 250, 19, 148, 72, 242, 208, 139, 48, 132, 84, 223,
20
+ 35, 25, 91, 61, 89, 243, 174, 162, 130, 99, 1, 131, 46,
21
+ 217, 81, 155, 124, 166, 235, 165, 190, 22, 12, 227, 97, 192,
22
+ 140, 58, 245, 115, 44, 37, 11, 187, 78, 137, 107, 83, 106,
23
+ 180, 241, 225, 230, 189, 69, 226, 244, 182, 102, 204, 149, 3,
24
+ 86, 212, 28, 30, 215, 251, 195, 142, 181, 233, 207, 191, 186,
25
+ 234, 119, 57, 175, 51, 201, 98, 113, 129, 121, 9, 173, 36,
26
+ 205, 249, 216, 229, 197, 185, 77, 68, 8, 134, 231, 161, 29,
27
+ 170, 237, 6, 112, 178, 210, 65, 123, 160, 17, 49, 194, 39,
28
+ 144, 32, 246, 96, 255, 150, 92, 177, 171, 158, 156, 82, 27,
29
+ 95, 147, 10, 239, 145, 133, 73, 238, 45, 79, 143, 59, 71,
30
+ 135, 109, 70, 214, 62, 105, 100, 42, 206, 203, 47, 252, 151,
31
+ 5, 122, 172, 127, 213, 26, 75, 14, 167, 90, 40, 20, 63,
32
+ 41, 136, 60, 76, 2, 184, 218, 176, 23, 85, 31, 138, 125,
33
+ 87, 199, 141, 116, 183, 196, 159, 114, 126, 21, 34, 18, 88,
34
+ 7, 153, 52, 110, 80, 222, 104, 101, 188, 219, 248, 200, 168,
35
+ 43, 64, 220, 254, 50, 164, 202, 16, 33, 240, 211, 93, 15,
36
+ 0, 111, 157, 54, 66, 74, 94, 193, 224
37
+ ]
38
+
39
+ Q1 = [
40
+ 117, 243, 198, 244, 219, 123, 251, 200, 74, 211, 230, 107, 69,
41
+ 125, 232, 75, 214, 50, 216, 253, 55, 113, 241, 225, 48, 15,
42
+ 248, 27, 135, 250, 6, 63, 94, 186, 174, 91, 138, 0, 188,
43
+ 157, 109, 193, 177, 14, 128, 93, 210, 213, 160, 132, 7, 20,
44
+ 181, 144, 44, 163, 178, 115, 76, 84, 146, 116, 54, 81, 56,
45
+ 176, 189, 90, 252, 96, 98, 150, 108, 66, 247, 16, 124, 40,
46
+ 39, 140, 19, 149, 156, 199, 36, 70, 59, 112, 202, 227, 133,
47
+ 203, 17, 208, 147, 184, 166, 131, 32, 255, 159, 119, 195, 204,
48
+ 3, 111, 8, 191, 64, 231, 43, 226, 121, 12, 170, 130, 65,
49
+ 58, 234, 185, 228, 154, 164, 151, 126, 218, 122, 23, 102, 148,
50
+ 161, 29, 61, 240, 222, 179, 11, 114, 167, 28, 239, 209, 83,
51
+ 62, 143, 51, 38, 95, 236, 118, 42, 73, 129, 136, 238, 33,
52
+ 196, 26, 235, 217, 197, 57, 153, 205, 173, 49, 139, 1, 24,
53
+ 35, 221, 31, 78, 45, 249, 72, 79, 242, 101, 142, 120, 92,
54
+ 88, 25, 141, 229, 152, 87, 103, 127, 5, 100, 175, 99, 182,
55
+ 254, 245, 183, 60, 165, 206, 233, 104, 68, 224, 77, 67, 105,
56
+ 41, 46, 172, 21, 89, 168, 10, 158, 110, 71, 223, 52, 53,
57
+ 106, 207, 220, 34, 201, 192, 155, 137, 212, 237, 171, 18, 162,
58
+ 13, 82, 187, 2, 47, 169, 215, 97, 30, 180, 80, 4, 246,
59
+ 194, 22, 37, 134, 86, 85, 9, 190, 145
60
+ ]
61
+
62
+ M0 = [
63
+ 3166450293, 3974898163, 538985414, 3014904308, 3671720923,
64
+ 33721211, 3806473211, 2661219016, 3385453642, 3570665939,
65
+ 404253670, 505323371, 2560101957, 2998024317, 2795950824,
66
+ 640071499, 1010587606, 2475919922, 2189618904, 1381144829,
67
+ 2071712823, 3149608817, 1532729329, 1195869153, 606354480,
68
+ 1364320783, 3132802808, 1246425883, 3216984199, 218984698,
69
+ 2964370182, 1970658879, 3537042782, 2105352378, 1717973422,
70
+ 976921435, 1499012234, 0, 3452801980, 437969053,
71
+ 2930650221, 2139073473, 724289457, 3200170254, 3772817536,
72
+ 2324303965, 993743570, 1684323029, 3638069408, 3890718084,
73
+ 1600120839, 454758676, 741130933, 4244419728, 825304876,
74
+ 2155898275, 1936927410, 202146163, 2037997388, 1802191188,
75
+ 1263207058, 1397975412, 2492763958, 2206408529, 707409464,
76
+ 3301219504, 572704957, 3587569754, 3183330300, 1212708960,
77
+ 4294954594, 1280051094, 1094809452, 3351766594, 3958056183,
78
+ 471602192, 1566401404, 909517352, 1734852647, 3924406156,
79
+ 1145370899, 336915093, 4126522268, 3486456007, 1061104932,
80
+ 3233866566, 1920129851, 1414818928, 690572490, 4042274275,
81
+ 134807173, 3334870987, 4092808977, 2358043856, 2762234259,
82
+ 3402274488, 1751661478, 3099086211, 943204384, 3857002239,
83
+ 2913818271, 185304183, 3368558019, 2577006540, 1482222851,
84
+ 421108335, 235801096, 2509602495, 1886408768, 4160172263,
85
+ 1852755755, 522153698, 3048553849, 151588620, 1633760426,
86
+ 1465325186, 2678000449, 2644344890, 286352618, 623234489,
87
+ 2947538404, 1162152090, 3755969956, 2745392279, 3941258622,
88
+ 892688602, 3991785594, 1128528919, 4177054566, 4227576212,
89
+ 926405537, 4210704413, 3267520573, 3031747824, 842161630,
90
+ 2627498419, 1448535819, 3823360626, 2273796263, 353704732,
91
+ 4193860335, 1667481553, 875866451, 2593817918, 2981184143,
92
+ 2088554803, 2290653990, 1027450463, 2711738348, 3840204662,
93
+ 2172752938, 2442199369, 252705665, 4008618632, 370565614,
94
+ 3621221153, 2543318468, 2779097114, 4278075371, 1835906521,
95
+ 2021174981, 3318050105, 488498585, 1987486925, 1044307117,
96
+ 3419105073, 3065399179, 4025441025, 303177240, 1616954659,
97
+ 1785376989, 1296954911, 3469666638, 3739122733, 1431674361,
98
+ 2122209864, 555856463, 50559730, 2694850149, 1583225230,
99
+ 1515873912, 1701137244, 1650609752, 4261233945, 101119117,
100
+ 1077970661, 4075994776, 859024471, 387420263, 84250239,
101
+ 3907542533, 1330609508, 2307484335, 269522275, 1953771446,
102
+ 168457726, 1549570805, 2610656439, 757936956, 808507045,
103
+ 774785486, 1229556201, 1179021928, 2004309316, 2829637856,
104
+ 2526413901, 673758531, 2846435689, 3654908201, 2256965934,
105
+ 3520169900, 4109650453, 2374833497, 3604382376, 3115957258,
106
+ 1111625118, 4143366510, 791656519, 3722249951, 589510964,
107
+ 3435946549, 4059153514, 3250655951, 2240146396, 2408554018,
108
+ 1903272393, 2425417920, 2863289243, 16904585, 2341200340,
109
+ 1313770733, 2391699371, 2880152082, 1869561506, 3873854477,
110
+ 3688624722, 2459073467, 3082270210, 1768540719, 960092585,
111
+ 3553823959, 2812748641, 2728570142, 3284375988, 1819034704,
112
+ 117900548, 67403766, 656885442, 2896996118, 3503322661,
113
+ 1347425158, 3705468758, 2223250005, 3789639945, 2054825406,
114
+ 320073617
115
+ ]
116
+
117
+ M1 = [
118
+ 2849585465, 1737496343, 3010567324, 3906119334, 67438343,
119
+ 4254618194, 2741338240, 1994384612, 2584233285, 2449623883,
120
+ 2158026976, 2019973722, 3839733679, 3719326314, 3518980963,
121
+ 943073834, 223667942, 3326287904, 895667404, 2562650866,
122
+ 404623890, 4146392043, 3973554593, 1819754817, 1136470056,
123
+ 1966259388, 936672123, 647727240, 4201647373, 335103044,
124
+ 2494692347, 1213890174, 4068082435, 3504639116, 2336732854,
125
+ 809247780, 2225465319, 1413573483, 3741769181, 600137824,
126
+ 424017405, 1537423930, 1030275778, 1494584717, 4079086828,
127
+ 2922473062, 2722000751, 2182502231, 1670713360, 22802415,
128
+ 2202908856, 781289094, 3652545901, 1361019779, 2605951658,
129
+ 2086886749, 2788911208, 3946839806, 2782277680, 3190127226,
130
+ 380087468, 202311945, 3811963120, 1629726631, 3236991120,
131
+ 2360338921, 981507485, 4120009820, 1937837068, 740766001,
132
+ 628543696, 199710294, 3145437842, 1323945678, 2314273025,
133
+ 1805590046, 1403597876, 1791291889, 3029976003, 4053228379,
134
+ 3783477063, 3865778200, 3184009762, 1158584472, 3798867743,
135
+ 4106859443, 3056563316, 1724643576, 3439303065, 2515145748,
136
+ 65886296, 1459084508, 3571551115, 471536917, 514695842,
137
+ 3607942099, 4213957346, 3273509064, 2384027230, 3049401388,
138
+ 3918088521, 3474112961, 3212744085, 3122691453, 3932426513,
139
+ 2005142283, 963495365, 2942994825, 869366908, 3382800753,
140
+ 1657733119, 1899477947, 2180714255, 2034087349, 156361185,
141
+ 2916892222, 606945087, 3450107510, 4187837781, 3639509634,
142
+ 3850780736, 3316545656, 3117229349, 1292146326, 1146451831,
143
+ 134876686, 2249412688, 3878746103, 2714974007, 490797818,
144
+ 2855559521, 3985395278, 112439472, 1886147668, 2989126515,
145
+ 3528604475, 1091280799, 2072707586, 2693322968, 290452467,
146
+ 828885963, 3259377447, 666920807, 2427780348, 539506744,
147
+ 4135519236, 1618495560, 4281263589, 2517060684, 1548445029,
148
+ 2982619947, 2876214926, 2651669058, 2629563893, 1391647707,
149
+ 468929098, 1604730173, 2472125604, 180140473, 4013619705,
150
+ 2448364307, 2248017928, 1224839569, 3999340054, 763158238,
151
+ 1337073953, 2403512753, 1004237426, 1203253039, 2269691839,
152
+ 1831644846, 1189331136, 3596041276, 1048943258, 1764338089,
153
+ 1685933903, 714375553, 3460902446, 3407333062, 801794409,
154
+ 4240686525, 2539430819, 90106088, 2060512749, 2894582225,
155
+ 2140013829, 3585762404, 447260069, 1270294054, 247054014,
156
+ 2808121223, 1526257109, 673330742, 336665371, 1071543669,
157
+ 695851481, 2292903662, 1009986861, 1281325433, 45529015,
158
+ 3096890058, 3663213877, 2963064004, 402408259, 1427801220,
159
+ 536235341, 2317113689, 2100867762, 1470903091, 3340292047,
160
+ 2381579782, 1953059667, 3077872539, 3304429463, 2673257901,
161
+ 1926947811, 2127948522, 357233908, 580816783, 312650667,
162
+ 1481532002, 132669279, 2581929245, 876159779, 1858205430,
163
+ 1346661484, 3730649650, 1752319558, 1697030304, 3163803085,
164
+ 3674462938, 4173773498, 3371867806, 2827146966, 735014510,
165
+ 1079013488, 3706422661, 4269083146, 847942547, 2760761311,
166
+ 3393988905, 269753372, 561240023, 4039947444, 3540636884,
167
+ 1561365130, 266490193, 0, 1872369945, 2648709658,
168
+ 915379348, 1122420679, 1257032137, 1593692882, 3249241983,
169
+ 3772295336
170
+ ]
171
+
172
+ M2 = [
173
+ 3161832498, 3975408673, 549855299, 3019158473, 3671841283,
174
+ 41616011, 3808158251, 2663948026, 3377121772, 3570652169,
175
+ 417732715, 510336671, 2554697742, 2994582072, 2800264914,
176
+ 642459319, 1020673111, 2469565322, 2195227374, 1392333464,
177
+ 2067233748, 3144792887, 1542544279, 1205946243, 607134780,
178
+ 1359958498, 3136862918, 1243302643, 3213344584, 234491248,
179
+ 2953228467, 1967093214, 3529429757, 2109373728, 1722705457,
180
+ 979057315, 1502239004, 0, 3451702675, 446503648,
181
+ 2926423596, 2143387563, 733031367, 3188637369, 3766542496,
182
+ 2321386000, 1003633490, 1691706554, 3634419848, 3884246949,
183
+ 1594318824, 454302481, 750070978, 4237360308, 824979751,
184
+ 2158198885, 1941074730, 208866433, 2035054943, 1800694593,
185
+ 1267878658, 1400132457, 2486604943, 2203157279, 708323894,
186
+ 3299919004, 582820552, 3579500024, 3187457475, 1214269560,
187
+ 4284678094, 1284918279, 1097613687, 3343042534, 3958893348,
188
+ 470817812, 1568431459, 908604962, 1730635712, 3918326191,
189
+ 1142113529, 345314538, 4120704443, 3485978392, 1059340077,
190
+ 3225862371, 1916498651, 1416647788, 701114700, 4041470005,
191
+ 142936318, 3335243287, 4078039887, 2362477796, 2761139289,
192
+ 3401108118, 1755736123, 3095640141, 941635624, 3858752814,
193
+ 2912922966, 192351108, 3368273949, 2580322815, 1476614381,
194
+ 426711450, 235408906, 2512360830, 1883271248, 4159174448,
195
+ 1848340175, 534912878, 3044652349, 151783695, 1638555956,
196
+ 1468159766, 2671877899, 2637864320, 300552548, 632890829,
197
+ 2951000029, 1167738120, 3752124301, 2744623964, 3934186197,
198
+ 903492952, 3984256464, 1125598204, 4167497931, 4220844977,
199
+ 933312467, 4196268608, 3258827368, 3035673804, 853422685,
200
+ 2629016689, 1443583719, 3815957466, 2275903328, 354161947,
201
+ 4193253690, 1674666943, 877868201, 2587794053, 2978984258,
202
+ 2083749073, 2284226715, 1029651878, 2716639703, 3832997087,
203
+ 2167046548, 2437517569, 260116475, 4001951402, 384702049,
204
+ 3609319283, 2546243573, 2769986984, 4276878911, 1842965941,
205
+ 2026207406, 3308897645, 496573925, 1993176740, 1051541212,
206
+ 3409038183, 3062609479, 4009881435, 303567390, 1612931269,
207
+ 1792895664, 1293897206, 3461271273, 3727548028, 1442403741,
208
+ 2118680154, 558834098, 66192250, 2691014694, 1586388505,
209
+ 1517836902, 1700554059, 1649959502, 4246338885, 109905652,
210
+ 1088766086, 4070109886, 861352876, 392632208, 92210574,
211
+ 3892701278, 1331974013, 2309982570, 274927765, 1958114351,
212
+ 184420981, 1559583890, 2612501364, 758918451, 816132310,
213
+ 785264201, 1240025481, 1181238898, 2000975701, 2833295576,
214
+ 2521667076, 675489981, 2842274089, 3643398521, 2251196049,
215
+ 3517763975, 4095079498, 2371456277, 3601389186, 3104487868,
216
+ 1117667853, 4134467265, 793194424, 3722435846, 590619449,
217
+ 3426077794, 4050317764, 3251618066, 2245821931, 2401406878,
218
+ 1909027233, 2428539120, 2862328403, 25756145, 2345962465,
219
+ 1324174988, 2393607791, 2870127522, 1872916286, 3859670612,
220
+ 3679640562, 2461766267, 3070408630, 1764714954, 967391705,
221
+ 3554136844, 2808194851, 2719916717, 3283403673, 1817209924,
222
+ 117704453, 83231871, 667035462, 2887167143, 3492139126,
223
+ 1350979603, 3696680183, 2220196890, 3775521105, 2059303461,
224
+ 328274927
225
+ ]
226
+
227
+ M3 = [
228
+ 3644434905, 2417452944, 1906094961, 3534153938, 84345861,
229
+ 2555575704, 1702929253, 3756291807, 138779144, 38507010,
230
+ 2699067552, 1717205094, 3719292125, 2959793584, 3210990015,
231
+ 908736566, 1424362836, 1126221379, 1657550178, 3203569854,
232
+ 504502302, 619444004, 3617713367, 2000776311, 3173532605,
233
+ 851211570, 3564845012, 2609391259, 1879964272, 4181988345,
234
+ 2986054833, 1518225498, 2047079034, 3834433764, 1203145543,
235
+ 1009004604, 2783413413, 1097552961, 115203846, 3311412165,
236
+ 1174214981, 2738510755, 1757560168, 361584917, 569176865,
237
+ 828812849, 1047503422, 374833686, 2500879253, 1542390107,
238
+ 1303937869, 2441490065, 3043875253, 528699679, 1403689811,
239
+ 1667071075, 996714043, 1073670975, 3593512406, 628801061,
240
+ 2813073063, 252251151, 904979253, 598171939, 4036018416,
241
+ 2951318703, 2157787776, 2455565714, 2165076865, 657533991,
242
+ 1993352566, 3881176039, 2073213819, 3922611945, 4043409905,
243
+ 2669570975, 2838778793, 3304155844, 2579739801, 2539385239,
244
+ 2202526083, 1796793963, 3357720008, 244860174, 1847583342,
245
+ 3384014025, 796177967, 3422054091, 4288269567, 3927217642,
246
+ 3981968365, 4158412535, 3784037601, 454368283, 2913083053,
247
+ 215209740, 736295723, 499696413, 425627161, 3257710018,
248
+ 2303322505, 314691346, 2123743102, 545110560, 1678895716,
249
+ 2215344004, 1841641837, 1787408234, 3514577873, 2708588961,
250
+ 3472843470, 935031095, 4212097531, 1035303229, 1373702481,
251
+ 3695095260, 759112749, 2759249316, 2639657373, 4001552622,
252
+ 2252400006, 2927150510, 3441801677, 76958980, 1433879637,
253
+ 168691722, 324044307, 821552944, 3543638483, 1090133312,
254
+ 878815796, 2353982860, 3014657715, 1817473132, 712225322,
255
+ 1379652178, 194986251, 2332195723, 2295898248, 1341329743,
256
+ 1741369703, 1177010758, 3227985856, 3036450996, 674766888,
257
+ 2131031679, 2018009208, 786825006, 122459655, 1264933963,
258
+ 3341529543, 1871620975, 222469645, 3153435835, 4074459890,
259
+ 4081720307, 2789040038, 1503957849, 3166243516, 989458234,
260
+ 4011037167, 4261971454, 26298625, 1628892769, 2094935420,
261
+ 2988527538, 1118932802, 3681696731, 3090106296, 1220511560,
262
+ 749628716, 3821029091, 1463604823, 2241478277, 698968361,
263
+ 2102355069, 2491493012, 1227804233, 398904087, 3395891146,
264
+ 3284008131, 1554224988, 1592264030, 3505224400, 2278665351,
265
+ 2382725006, 3127170490, 2829392552, 3072740279, 3116240569,
266
+ 1619502944, 4174732024, 573974562, 286987281, 3732226014,
267
+ 2044275065, 2867759274, 858602547, 1601784927, 3065447094,
268
+ 2529867926, 1479924312, 2630135964, 4232255484, 444880154,
269
+ 4132249590, 475630108, 951221560, 2889045932, 416270104,
270
+ 4094070260, 1767076969, 1956362100, 4120364277, 1454219094,
271
+ 3672339162, 3588914901, 1257510218, 2660180638, 2729120418,
272
+ 1315067982, 3898542056, 3843922405, 958608441, 3254152897,
273
+ 1147949124, 1563614813, 1917216882, 648045862, 2479733907,
274
+ 64674563, 3334142150, 4204710138, 2195105922, 3480103887,
275
+ 1349533776, 3951418603, 1963654773, 2324902538, 2380244109,
276
+ 1277807180, 337383444, 1943478643, 3434410188, 164942601,
277
+ 277503248, 3796963298, 0, 2585358234, 3759840736,
278
+ 2408855183, 3871818470, 3972614892, 4258422525, 2877276587,
279
+ 3634946264
280
+ ]
281
+ #:startdoc:
282
+
283
+ # Takes a mandatory key (16, 24 or 32 bytes), and an options
284
+ # hash as follows:
285
+ # :mode => :ecb (default) or :cbc
286
+ # :iv => optional 16 byte initialization vector (randomly generated if not supplied)
287
+ # :padding => :none (default) or :zero_byte
288
+ def initialize(key_string, opts={})
289
+
290
+ self.mode = opts[:mode] # use setter for validation
291
+ self.padding = opts[:padding] # use setter for validation
292
+ @iv = opts[:iv] || generate_iv(BLOCK_SIZE) unless @mode == Mode::ECB
293
+
294
+ # The key consists of k=len/8 (2, 3 or 4) 64-bit units.
295
+ key = key_string.unpack("C*")
296
+ @key_size = key.length
297
+
298
+ # We must derive three vectors Me, Mo, and S, each with k 32-bit
299
+ # words, from the 2k words in the key.
300
+ #
301
+ # Me = (key[0], key[2], ..., key[2k-2]) (even words)
302
+ # Mo = (key[1], key[3], ..., key[2k-1]) (odd words)
303
+ #
304
+ # The third vector is derived by multiplying each of the k groups
305
+ # of 8 bytes from the key by a 4x8 matrix, to get k 32-bit words.
306
+ #
307
+ # S = (S[k-1], S[k-2], ..., S[0])
308
+ #
309
+ # where S[i] are the 4 bytes from the multiplication, interpreted
310
+ # as a 32-bit word. As described later, mds_rem is equivalent to
311
+ # the matrix multiplication, but faster.
312
+ le_longs = key_string.unpack("V*")
313
+
314
+ # The words of the expanded key K are defined using the h function:
315
+ #
316
+ # rho = 2^24 + 2^16 + 2^8 + 2^0 (0x01010101)
317
+ # A[i] = h(2i*rho, Me)
318
+ # B[i] = ROL(h(2(i+1)*rho, Mo), 8)
319
+ # K[2i] = (A[i] + B[i]) mod 2^32
320
+ # K[2i+1] = ROL((A[i] + 2B[i]) mod 2^32, 9)
321
+ #
322
+ # rho has the property that, for i = 0..255, the word i*rho
323
+ # consists of four equal bytes, each with the value i. The function
324
+ # h is only applied to words of this type, so we only pass it the
325
+ # value of i.
326
+ k = []
327
+
328
+ # The key-dependent S-boxes used in the g() function are created
329
+ # below. They are defined by g(X) = h(X, S), where S is the vector
330
+ # derived from the key. That is, for i=0..3, the S-box S[i] is
331
+ # formed by mapping from x[i] to y[i] in the h function.
332
+ #
333
+ # The relevant lookup tables qN have been precomputed and stored in
334
+ # tables.h; we also perform full key precomputations incorporating
335
+ # the MDS matrix multiplications.
336
+ xS0, xS1, xS2, xS3 = [], [], [], []
337
+ case @key_size
338
+ when 16
339
+ s7, s6, s5, s4 = *mds_rem(le_longs[0], le_longs[1])
340
+ s3, s2, s1, s0 = *mds_rem(le_longs[2], le_longs[3])
341
+ a, b = 0, 0
342
+ (0..38).step(2) do |i|
343
+ j = i + 1
344
+ a = M0[Q0[Q0[i] ^ key[8]] ^ key[0]] ^
345
+ M1[Q0[Q1[i] ^ key[9]] ^ key[1]] ^
346
+ M2[Q1[Q0[i] ^ key[10]] ^ key[2]] ^
347
+ M3[Q1[Q1[i] ^ key[11]] ^ key[3]]
348
+ b = M0[Q0[Q0[j] ^ key[12]] ^ key[4]] ^
349
+ M1[Q0[Q1[j] ^ key[13]] ^ key[5]] ^
350
+ M2[Q1[Q0[j] ^ key[14]] ^ key[6]] ^
351
+ M3[Q1[Q1[j] ^ key[15]] ^ key[7]]
352
+ b = mask32(b << 8) | (b >> 24)
353
+ a = mask32(a+b)
354
+ k.push(a)
355
+ a = mask32(a+b)
356
+ k.push(mask32(a << 9) | a >> 23)
357
+ end
358
+ (0..255).each do |i|
359
+ xS0[i] = M0[Q0[Q0[i] ^ s4] ^ s0]
360
+ xS1[i] = M1[Q0[Q1[i] ^ s5] ^ s1]
361
+ xS2[i] = M2[Q1[Q0[i] ^ s6] ^ s2]
362
+ xS3[i] = M3[Q1[Q1[i] ^ s7] ^ s3]
363
+ end
364
+ when 24
365
+ sb, sa, s9, s8 = *mds_rem(le_longs[0], le_longs[1])
366
+ s7, s6, s5, s4 = *mds_rem(le_longs[2], le_longs[3])
367
+ s3, s2, s1, s0 = *mds_rem(le_longs[4], le_longs[5])
368
+ i, j = 0, 1
369
+ (0..38).step(2) do |i|
370
+ j = i + 1
371
+ a = M0[Q0[Q0[Q1[i] ^ key[16]] ^ key[8]] ^ key[0]] ^
372
+ M1[Q0[Q1[Q1[i] ^ key[17]] ^ key[9]] ^ key[1]] ^
373
+ M2[Q1[Q0[Q0[i] ^ key[18]] ^ key[10]] ^ key[2]] ^
374
+ M3[Q1[Q1[Q0[i] ^ key[19]] ^ key[11]] ^ key[3]]
375
+ b = M0[Q0[Q0[Q1[j] ^ key[20]] ^ key[12]] ^ key[4]] ^
376
+ M1[Q0[Q1[Q1[j] ^ key[21]] ^ key[13]] ^ key[5]] ^
377
+ M2[Q1[Q0[Q0[j] ^ key[22]] ^ key[14]] ^ key[6]] ^
378
+ M3[Q1[Q1[Q0[j] ^ key[23]] ^ key[15]] ^ key[7]]
379
+ b = mask32(b << 8) | (b >> 24)
380
+ a = mask32(a+b)
381
+ k.push(a)
382
+ a = mask32(a+b)
383
+ k.push(mask32(a << 9) | a >> 23)
384
+ end
385
+ (0..255).each do |i|
386
+ xS0[i] = M0[Q0[Q0[Q1[i] ^ s8] ^ s4] ^ s0]
387
+ xS1[i] = M1[Q0[Q1[Q1[i] ^ s9] ^ s5] ^ s1]
388
+ xS2[i] = M2[Q1[Q0[Q0[i] ^ sa] ^ s6] ^ s2]
389
+ xS3[i] = M3[Q1[Q1[Q0[i] ^ sb] ^ s7] ^ s3]
390
+ end
391
+ when 32
392
+ sf, se, sd, sc = *mds_rem(le_longs[0], le_longs[1])
393
+ sb, sa, s9, s8 = *mds_rem(le_longs[2], le_longs[3])
394
+ s7, s6, s5, s4 = *mds_rem(le_longs[4], le_longs[5])
395
+ s3, s2, s1, s0 = *mds_rem(le_longs[6], le_longs[7])
396
+ i, j = 0, 1
397
+ (0..38).step(2) do |i|
398
+ j = i + 1
399
+ a = M0[Q0[Q0[Q1[Q1[i] ^ key[24]] ^ key[16]] ^ key[8]] ^ key[0]] ^
400
+ M1[Q0[Q1[Q1[Q0[i] ^ key[25]] ^ key[17]] ^ key[9]] ^ key[1]] ^
401
+ M2[Q1[Q0[Q0[Q0[i] ^ key[26]] ^ key[18]] ^ key[10]] ^ key[2]] ^
402
+ M3[Q1[Q1[Q0[Q1[i] ^ key[27]] ^ key[19]] ^ key[11]] ^ key[3]]
403
+ b = M0[Q0[Q0[Q1[Q1[j] ^ key[28]] ^ key[20]] ^ key[12]] ^ key[4]] ^
404
+ M1[Q0[Q1[Q1[Q0[j] ^ key[29]] ^ key[21]] ^ key[13]] ^ key[5]] ^
405
+ M2[Q1[Q0[Q0[Q0[j] ^ key[30]] ^ key[22]] ^ key[14]] ^ key[6]] ^
406
+ M3[Q1[Q1[Q0[Q1[j] ^ key[31]] ^ key[23]] ^ key[15]] ^ key[7]]
407
+ b = mask32(b << 8) | (b >> 24)
408
+ a = mask32(a+b)
409
+ k.push(a)
410
+ a = mask32(a+b)
411
+ k.push(mask32(a << 9) | a >> 23)
412
+ end
413
+ (0..255).each do |i|
414
+ xS0[i] = M0[Q0[Q0[Q1[Q1[i]^sc]^s8]^s4]^s0]
415
+ xS1[i] = M1[Q0[Q1[Q1[Q0[i]^sd]^s9]^s5]^s1]
416
+ xS2[i] = M2[Q1[Q0[Q0[Q0[i]^se]^sa]^s6]^s2]
417
+ xS3[i] = M3[Q1[Q1[Q0[Q1[i]^sf]^sb]^s7]^s3]
418
+ end
419
+ else
420
+ raise ArgumentError, "invalid key length #{@key_size} (expecting 16, 24 or 32 bytes)"
421
+ end
422
+
423
+ @k = k
424
+ @s = [ xS0, xS1, xS2, xS3 ]
425
+
426
+ end
427
+
428
+ # Assign the initialization vector.
429
+ # This does not make sense for ECB mode. Also the IV length
430
+ # must be a multiple of the block size.
431
+ def iv=(iv)
432
+ raise ArgumentError, 'cannot specify initialization vector for ECB mode' if @mode == Mode::ECB
433
+ raise ArgumentError, "initialization vectcor is not a multiple of #{BLOCK_SIZE} bytes" unless (iv.length % BLOCK_SIZE).zero?
434
+ @iv = iv
435
+ end
436
+
437
+ # Set the mode of the cipher (Mode::ECB == :ecb or
438
+ # Mode::CBC == :cbc).
439
+ # If the cipher has an IV already and mode is now
440
+ # set to Mode::ECB then the IV will be ignored for any
441
+ # encrypt/decrypt operations.
442
+ def mode=(mode)
443
+ @mode = Mode::validate(mode)
444
+ end
445
+
446
+ # Set the padding scheme for the (CBC mode) cipher
447
+ # (Padding::NONE == :none or Padding::ZERO_BYTE ==
448
+ # :zero_byte).
449
+ def padding=(scheme)
450
+ @padding = Padding::validate(scheme)
451
+ end
452
+
453
+ # Return the cipher's block size in bytes.
454
+ def self.block_size
455
+ BLOCK_SIZE
456
+ end
457
+
458
+ # Encrypt a plaintext string, chunking as required for
459
+ # CBC mode.
460
+ def encrypt(plaintext)
461
+ padded_plaintext = Padding::pad(plaintext, BLOCK_SIZE, self.padding)
462
+ result = ''
463
+ if @mode == Mode::CBC
464
+ @iv = generate_iv(BLOCK_SIZE) unless @iv
465
+ ciphertext_block = @iv
466
+ end
467
+ (0..padded_plaintext.length-1).step(BLOCK_SIZE) do |block_ptr|
468
+ (0..BLOCK_SIZE-1).each { |i| padded_plaintext[block_ptr+i] = ( padded_plaintext[block_ptr+i].ord ^ ciphertext_block[i].ord ).chr } if Mode::CBC == @mode
469
+ result << ciphertext_block = self.encrypt_block(padded_plaintext[block_ptr, BLOCK_SIZE])
470
+ end
471
+ result
472
+ end
473
+
474
+ # Decrypt a ciphertext string, unchunking as required for
475
+ # chaining modes. If @iv is not set then we use the first block
476
+ # as the initialization vector when chaining.
477
+ def decrypt(ciphertext)
478
+ raise ArgumentError, "Ciphertext is not a multiple of #{BLOCK_SIZE} bytes" unless (ciphertext.length % BLOCK_SIZE).zero?
479
+ result = ''
480
+ if Mode::CBC == @mode
481
+ if @iv
482
+ feedback = @iv
483
+ else
484
+ feedback = ciphertext[0, BLOCK_SIZE]
485
+ ciphertext = ciphertext[BLOCK_SIZE..-1]
486
+ end
487
+ end
488
+ (0..ciphertext.length-1).step(BLOCK_SIZE) do |block_ptr|
489
+ ciphertext_block = ciphertext[block_ptr, BLOCK_SIZE]
490
+ plaintext_block = self.decrypt_block(ciphertext_block)
491
+ (0..BLOCK_SIZE-1).each { |i| plaintext_block[i] = (plaintext_block[i].ord ^ feedback[i].ord).chr } if Mode::CBC == @mode
492
+ result << plaintext_block
493
+ feedback = ciphertext_block
494
+ end
495
+ Padding::unpad(result, BLOCK_SIZE, self.padding)
496
+ end
497
+
498
+ # Encrypt a single block (16 bytes).
499
+ def encrypt_block(plain_text)
500
+
501
+ words = plain_text.unpack('V4')
502
+ k = @k
503
+
504
+ r0 = k[0] ^ words[0]
505
+ r1 = k[1] ^ words[1]
506
+ r2 = k[2] ^ words[2]
507
+ r3 = k[3] ^ words[3]
508
+
509
+ xS0, xS1, xS2, xS3 = *@s
510
+
511
+ # i = 0
512
+ t0 = xS0[r0 & 0xff] ^
513
+ xS1[(r0 >> 8) & 0xff] ^
514
+ xS2[(r0 >> 16) & 0xff] ^
515
+ xS3[(r0 >> 24) & 0xff]
516
+ t1 = xS0[(r1 >> 24) & 0xff] ^
517
+ xS1[r1 & 0xff] ^
518
+ xS2[(r1 >> 8) & 0xff] ^
519
+ xS3[(r1 >> 16) & 0xff]
520
+
521
+ r2 ^= mask32(t0 + t1 + k[8])
522
+ r2 = (r2 >> 1 & 0x7fffffff) | mask32(r2 << 31)
523
+
524
+ r3 = ((r3 >> 31) & 1) | mask32(r3 << 1)
525
+ r3 ^= mask32(t0 + mask32(t1 << 1) + k[9])
526
+
527
+ t0 = xS0[r2 & 0xff] ^
528
+ xS1[(r2 >> 8) & 0xff] ^
529
+ xS2[(r2 >> 16) & 0xff] ^
530
+ xS3[(r2 >> 24) & 0xff]
531
+ t1 = xS0[(r3 >> 24) & 0xff] ^
532
+ xS1[r3 & 0xff] ^
533
+ xS2[(r3 >> 8) & 0xff] ^
534
+ xS3[(r3 >> 16) & 0xff]
535
+
536
+ r0 ^= mask32(t0 + t1 + k[10])
537
+ r0 = (r0 >> 1 & 0x7fffffff) | mask32(r0 << 31)
538
+
539
+ r1 = ((r1 >> 31) & 1) | mask32(r1 << 1)
540
+ r1 ^= mask32(t0 + mask32(t1 << 1) + k[11])
541
+
542
+ # i = 1
543
+ t0 = xS0[r0 & 0xff] ^
544
+ xS1[(r0 >> 8) & 0xff] ^
545
+ xS2[(r0 >> 16) & 0xff] ^
546
+ xS3[(r0 >> 24) & 0xff]
547
+ t1 = xS0[(r1 >> 24) & 0xff] ^
548
+ xS1[r1 & 0xff] ^
549
+ xS2[(r1 >> 8) & 0xff] ^
550
+ xS3[(r1 >> 16) & 0xff]
551
+
552
+ r2 ^= mask32(t0 + t1 + k[12])
553
+ r2 = (r2 >> 1 & 0x7fffffff) | mask32(r2 << 31)
554
+
555
+ r3 = ((r3 >> 31) & 1) | mask32(r3 << 1)
556
+ r3 ^= mask32(t0 + mask32(t1 << 1) + k[13])
557
+
558
+ t0 = xS0[r2 & 0xff] ^
559
+ xS1[(r2 >> 8) & 0xff] ^
560
+ xS2[(r2 >> 16) & 0xff] ^
561
+ xS3[(r2 >> 24) & 0xff]
562
+ t1 = xS0[(r3 >> 24) & 0xff] ^
563
+ xS1[r3 & 0xff] ^
564
+ xS2[(r3 >> 8) & 0xff] ^
565
+ xS3[(r3 >> 16) & 0xff]
566
+
567
+ r0 ^= mask32(t0 + t1 + k[14])
568
+ r0 = (r0 >> 1 & 0x7fffffff) | mask32(r0 << 31)
569
+
570
+ r1 = ((r1 >> 31) & 1) | mask32(r1 << 1)
571
+ r1 ^= mask32(t0 + mask32(t1 << 1) + k[15])
572
+
573
+ # i = 2
574
+ t0 = xS0[r0 & 0xff] ^
575
+ xS1[(r0 >> 8) & 0xff] ^
576
+ xS2[(r0 >> 16) & 0xff] ^
577
+ xS3[(r0 >> 24) & 0xff]
578
+ t1 = xS0[(r1 >> 24) & 0xff] ^
579
+ xS1[r1 & 0xff] ^
580
+ xS2[(r1 >> 8) & 0xff] ^
581
+ xS3[(r1 >> 16) & 0xff]
582
+
583
+ r2 ^= mask32(t0 + t1 + k[16])
584
+ r2 = (r2 >> 1 & 0x7fffffff) | mask32(r2 << 31)
585
+
586
+ r3 = ((r3 >> 31) & 1) | mask32(r3 << 1)
587
+ r3 ^= mask32(t0 + mask32(t1 << 1) + k[17])
588
+
589
+ t0 = xS0[r2 & 0xff] ^
590
+ xS1[(r2 >> 8) & 0xff] ^
591
+ xS2[(r2 >> 16) & 0xff] ^
592
+ xS3[(r2 >> 24) & 0xff]
593
+ t1 = xS0[(r3 >> 24) & 0xff] ^
594
+ xS1[r3 & 0xff] ^
595
+ xS2[(r3 >> 8) & 0xff] ^
596
+ xS3[(r3 >> 16) & 0xff]
597
+
598
+ r0 ^= mask32(t0 + t1 + k[18])
599
+ r0 = (r0 >> 1 & 0x7fffffff) | mask32(r0 << 31)
600
+
601
+ r1 = ((r1 >> 31) & 1) | mask32(r1 << 1)
602
+ r1 ^= mask32(t0 + mask32(t1 << 1) + k[19])
603
+
604
+ # i = 3
605
+ t0 = xS0[r0 & 0xff] ^
606
+ xS1[(r0 >> 8) & 0xff] ^
607
+ xS2[(r0 >> 16) & 0xff] ^
608
+ xS3[(r0 >> 24) & 0xff]
609
+ t1 = xS0[(r1 >> 24) & 0xff] ^
610
+ xS1[r1 & 0xff] ^
611
+ xS2[(r1 >> 8) & 0xff] ^
612
+ xS3[(r1 >> 16) & 0xff]
613
+
614
+ r2 ^= mask32(t0 + t1 + k[20])
615
+ r2 = (r2 >> 1 & 0x7fffffff) | mask32(r2 << 31)
616
+
617
+ r3 = ((r3 >> 31) & 1) | mask32(r3 << 1)
618
+ r3 ^= mask32(t0 + mask32(t1 << 1) + k[21])
619
+
620
+ t0 = xS0[r2 & 0xff] ^
621
+ xS1[(r2 >> 8) & 0xff] ^
622
+ xS2[(r2 >> 16) & 0xff] ^
623
+ xS3[(r2 >> 24) & 0xff]
624
+ t1 = xS0[(r3 >> 24) & 0xff] ^
625
+ xS1[r3 & 0xff] ^
626
+ xS2[(r3 >> 8) & 0xff] ^
627
+ xS3[(r3 >> 16) & 0xff]
628
+
629
+ r0 ^= mask32(t0 + t1 + k[22])
630
+ r0 = (r0 >> 1 & 0x7fffffff) | mask32(r0 << 31)
631
+
632
+ r1 = ((r1 >> 31) & 1) | mask32(r1 << 1)
633
+ r1 ^= mask32(t0 + mask32(t1 << 1) + k[23])
634
+
635
+ # i = 4
636
+ t0 = xS0[r0 & 0xff] ^
637
+ xS1[(r0 >> 8) & 0xff] ^
638
+ xS2[(r0 >> 16) & 0xff] ^
639
+ xS3[(r0 >> 24) & 0xff]
640
+ t1 = xS0[(r1 >> 24) & 0xff] ^
641
+ xS1[r1 & 0xff] ^
642
+ xS2[(r1 >> 8) & 0xff] ^
643
+ xS3[(r1 >> 16) & 0xff]
644
+
645
+ r2 ^= mask32(t0 + t1 + k[24])
646
+ r2 = (r2 >> 1 & 0x7fffffff) | mask32(r2 << 31)
647
+
648
+ r3 = ((r3 >> 31) & 1) | mask32(r3 << 1)
649
+ r3 ^= mask32(t0 + mask32(t1 << 1) + k[25])
650
+
651
+ t0 = xS0[r2 & 0xff] ^
652
+ xS1[(r2 >> 8) & 0xff] ^
653
+ xS2[(r2 >> 16) & 0xff] ^
654
+ xS3[(r2 >> 24) & 0xff]
655
+ t1 = xS0[(r3 >> 24) & 0xff] ^
656
+ xS1[r3 & 0xff] ^
657
+ xS2[(r3 >> 8) & 0xff] ^
658
+ xS3[(r3 >> 16) & 0xff]
659
+
660
+ r0 ^= mask32(t0 + t1 + k[26])
661
+ r0 = (r0 >> 1 & 0x7fffffff) | mask32(r0 << 31);
662
+
663
+ r1 = ((r1 >> 31) & 1) | mask32(r1 << 1)
664
+ r1 ^= mask32(t0 + mask32(t1 << 1) + k[27])
665
+
666
+ # i = 5
667
+ t0 = xS0[r0 & 0xff] ^
668
+ xS1[(r0 >> 8) & 0xff] ^
669
+ xS2[(r0 >> 16) & 0xff] ^
670
+ xS3[(r0 >> 24) & 0xff]
671
+ t1 = xS0[(r1 >> 24) & 0xff] ^
672
+ xS1[r1 & 0xff] ^
673
+ xS2[(r1 >> 8) & 0xff] ^
674
+ xS3[(r1 >> 16) & 0xff]
675
+
676
+ r2 ^= mask32(t0 + t1 + k[28])
677
+ r2 = (r2 >> 1 & 0x7fffffff) | mask32(r2 << 31)
678
+
679
+ r3 = ((r3 >> 31) & 1) | mask32(r3 << 1)
680
+ r3 ^= mask32(t0 + mask32(t1 << 1) + k[29])
681
+
682
+ t0 = xS0[r2 & 0xff] ^
683
+ xS1[(r2 >> 8) & 0xff] ^
684
+ xS2[(r2 >> 16) & 0xff] ^
685
+ xS3[(r2 >> 24) & 0xff]
686
+ t1 = xS0[(r3 >> 24) & 0xff] ^
687
+ xS1[r3 & 0xff] ^
688
+ xS2[(r3 >> 8) & 0xff] ^
689
+ xS3[(r3 >> 16) & 0xff]
690
+
691
+ r0 ^= mask32(t0 + t1 + k[30])
692
+ r0 = (r0 >> 1 & 0x7fffffff) | mask32(r0 << 31)
693
+
694
+ r1 = ((r1 >> 31) & 1) | mask32(r1 << 1)
695
+ r1 ^= mask32(t0 + mask32(t1 << 1) + k[31])
696
+
697
+ # i = 6
698
+ t0 = xS0[r0 & 0xff] ^
699
+ xS1[(r0 >> 8) & 0xff] ^
700
+ xS2[(r0 >> 16) & 0xff] ^
701
+ xS3[(r0 >> 24) & 0xff]
702
+ t1 = xS0[(r1 >> 24) & 0xff] ^
703
+ xS1[r1 & 0xff] ^
704
+ xS2[(r1 >> 8) & 0xff] ^
705
+ xS3[(r1 >> 16) & 0xff]
706
+
707
+ r2 ^= mask32(t0 + t1 + k[32])
708
+ r2 = (r2 >> 1 & 0x7fffffff) | mask32(r2 << 31)
709
+
710
+ r3 = ((r3 >> 31) & 1) | mask32(r3 << 1)
711
+ r3 ^= mask32(t0 + mask32(t1 << 1) + k[33])
712
+
713
+ t0 = xS0[r2 & 0xff] ^
714
+ xS1[(r2 >> 8) & 0xff] ^
715
+ xS2[(r2 >> 16) & 0xff] ^
716
+ xS3[(r2 >> 24) & 0xff]
717
+ t1 = xS0[(r3 >> 24) & 0xff] ^
718
+ xS1[r3 & 0xff] ^
719
+ xS2[(r3 >> 8) & 0xff] ^
720
+ xS3[(r3 >> 16) & 0xff]
721
+
722
+ r0 ^= mask32(t0 + t1 + k[34])
723
+ r0 = (r0 >> 1 & 0x7fffffff) | mask32(r0 << 31)
724
+
725
+ r1 = ((r1 >> 31) & 1) | mask32(r1 << 1)
726
+ r1 ^= mask32(t0 + mask32(t1 << 1) + k[35])
727
+
728
+ # i = 7
729
+ t0 = xS0[r0 & 0xff] ^
730
+ xS1[(r0 >> 8) & 0xff] ^
731
+ xS2[(r0 >> 16) & 0xff] ^
732
+ xS3[(r0 >> 24) & 0xff]
733
+ t1 = xS0[(r1 >> 24) & 0xff] ^
734
+ xS1[r1 & 0xff] ^
735
+ xS2[(r1 >> 8) & 0xff] ^
736
+ xS3[(r1 >> 16) & 0xff]
737
+
738
+ r2 ^= mask32(t0 + t1 + k[36])
739
+ r2 = (r2 >> 1 & 0x7fffffff) | mask32(r2 << 31)
740
+
741
+ r3 = ((r3 >> 31) & 1) | mask32(r3 << 1)
742
+ r3 ^= mask32(t0 + mask32(t1 << 1) + k[37])
743
+
744
+ t0 = xS0[r2 & 0xff] ^
745
+ xS1[(r2 >> 8) & 0xff] ^
746
+ xS2[(r2 >> 16) & 0xff] ^
747
+ xS3[(r2 >> 24) & 0xff]
748
+ t1 = xS0[(r3 >> 24) & 0xff] ^
749
+ xS1[r3 & 0xff] ^
750
+ xS2[(r3 >> 8) & 0xff] ^
751
+ xS3[(r3 >> 16) & 0xff]
752
+
753
+ r0 ^= mask32(t0 + t1 + k[38])
754
+ r0 = (r0 >> 1 & 0x7fffffff) | mask32(r0 << 31)
755
+
756
+ r1 = ((r1 >> 31) & 1) | mask32(r1 << 1)
757
+ r1 ^= mask32(t0 + mask32(t1 << 1) + k[39])
758
+
759
+ [k[4] ^ r2, k[5] ^ r3, k[6] ^ r0, k[7] ^ r1].pack("V4")
760
+ end
761
+
762
+ # Decrypt a single block (16 bytes).
763
+ def decrypt_block(plain)
764
+ words = plain.unpack("V4")
765
+ k = @k
766
+
767
+ r0 = k[4] ^ words[0]
768
+ r1 = k[5] ^ words[1]
769
+ r2 = k[6] ^ words[2]
770
+ r3 = k[7] ^ words[3]
771
+
772
+ xS0, xS1, xS2, xS3 = *@s
773
+
774
+ # i = 7
775
+ t0 = xS0[r0 & 0xff] ^
776
+ xS1[r0 >> 8 & 0xff] ^
777
+ xS2[r0 >> 16 & 0xff] ^
778
+ xS3[r0 >> 24 & 0xff]
779
+ t1 = xS0[r1 >> 24 & 0xff] ^
780
+ xS1[r1 & 0xff] ^
781
+ xS2[r1 >> 8 & 0xff] ^
782
+ xS3[r1 >> 16 & 0xff]
783
+
784
+ r2 = r2 >> 31 & 0x1 | mask32(r2 << 1)
785
+ r2 ^= mask32(t0 + t1 + k[38])
786
+
787
+ r3 ^= mask32(t0 + mask32(t1 << 1) + k[39])
788
+ r3 = r3 >> 1 & 0x7fffffff | mask32(r3 << 31)
789
+
790
+ t0 = xS0[r2 & 0xff] ^
791
+ xS1[r2 >> 8 & 0xff] ^
792
+ xS2[r2 >> 16 & 0xff] ^
793
+ xS3[r2 >> 24 & 0xff]
794
+ t1 = xS0[r3 >> 24 & 0xff] ^
795
+ xS1[r3 & 0xff] ^
796
+ xS2[r3 >> 8 & 0xff] ^
797
+ xS3[r3 >> 16 & 0xff]
798
+
799
+ r0 = r0 >> 31 & 0x1 | mask32(r0 << 1)
800
+ r0 ^= mask32(t0 + t1 + k[36])
801
+
802
+ r1 ^= mask32(t0 + mask32(t1 << 1) + k[37])
803
+ r1 = r1 >> 1 & 0x7fffffff | mask32(r1 << 31)
804
+
805
+ # i = 6
806
+ t0 = xS0[r0 & 0xff] ^
807
+ xS1[r0 >> 8 & 0xff] ^
808
+ xS2[r0 >> 16 & 0xff] ^
809
+ xS3[r0 >> 24 & 0xff]
810
+ t1 = xS0[r1 >> 24 & 0xff] ^
811
+ xS1[r1 & 0xff] ^
812
+ xS2[r1 >> 8 & 0xff] ^
813
+ xS3[r1 >> 16 & 0xff]
814
+
815
+ r2 = r2 >> 31 & 0x1 | mask32(r2 << 1)
816
+ r2 ^= mask32(t0 + t1 + k[34])
817
+
818
+ r3 ^= mask32(t0 + mask32(t1 << 1) + k[35])
819
+ r3 = r3 >> 1 & 0x7fffffff | mask32(r3 << 31)
820
+
821
+ t0 = xS0[r2 & 0xff] ^
822
+ xS1[r2 >> 8 & 0xff] ^
823
+ xS2[r2 >> 16 & 0xff] ^
824
+ xS3[r2 >> 24 & 0xff]
825
+ t1 = xS0[r3 >> 24 & 0xff] ^
826
+ xS1[r3 & 0xff] ^
827
+ xS2[r3 >> 8 & 0xff] ^
828
+ xS3[r3 >> 16 & 0xff]
829
+
830
+ r0 = r0 >> 31 & 0x1 | mask32(r0 << 1)
831
+ r0 ^= mask32(t0 + t1 + k[32])
832
+
833
+ r1 ^= mask32(t0 + mask32(t1 << 1) + k[33])
834
+ r1 = r1 >> 1 & 0x7fffffff | mask32(r1 << 31)
835
+
836
+ # i = 5
837
+ t0 = xS0[r0 & 0xff] ^
838
+ xS1[r0 >> 8 & 0xff] ^
839
+ xS2[r0 >> 16 & 0xff] ^
840
+ xS3[r0 >> 24 & 0xff]
841
+ t1 = xS0[r1 >> 24 & 0xff] ^
842
+ xS1[r1 & 0xff] ^
843
+ xS2[r1 >> 8 & 0xff] ^
844
+ xS3[r1 >> 16 & 0xff]
845
+
846
+ r2 = r2 >> 31 & 0x1 | mask32(r2 << 1)
847
+ r2 ^= mask32(t0 + t1 + k[30])
848
+
849
+ r3 ^= mask32(t0 + mask32(t1 << 1) + k[31])
850
+ r3 = r3 >> 1 & 0x7fffffff | mask32(r3 << 31)
851
+
852
+ t0 = xS0[r2 & 0xff] ^
853
+ xS1[r2 >> 8 & 0xff] ^
854
+ xS2[r2 >> 16 & 0xff] ^
855
+ xS3[r2 >> 24 & 0xff]
856
+ t1 = xS0[r3 >> 24 & 0xff] ^
857
+ xS1[r3 & 0xff] ^
858
+ xS2[r3 >> 8 & 0xff] ^
859
+ xS3[r3 >> 16 & 0xff]
860
+
861
+ r0 = r0 >> 31 & 0x1 | mask32(r0 << 1)
862
+ r0 ^= mask32(t0 + t1 + k[28])
863
+
864
+ r1 ^= mask32(t0 + mask32(t1 << 1) + k[29])
865
+ r1 = r1 >> 1 & 0x7fffffff | mask32(r1 << 31)
866
+
867
+ # i = 4
868
+ t0 = xS0[r0 & 0xff] ^
869
+ xS1[r0 >> 8 & 0xff] ^
870
+ xS2[r0 >> 16 & 0xff] ^
871
+ xS3[r0 >> 24 & 0xff]
872
+ t1 = xS0[r1 >> 24 & 0xff] ^
873
+ xS1[r1 & 0xff] ^
874
+ xS2[r1 >> 8 & 0xff] ^
875
+ xS3[r1 >> 16 & 0xff]
876
+
877
+ r2 = r2 >> 31 & 0x1 | mask32(r2 << 1)
878
+ r2 ^= mask32(t0 + t1 + k[26])
879
+
880
+ r3 ^= mask32(t0 + mask32(t1 << 1) + k[27])
881
+ r3 = r3 >> 1 & 0x7fffffff | mask32(r3 << 31)
882
+
883
+ t0 = xS0[r2 & 0xff] ^
884
+ xS1[r2 >> 8 & 0xff] ^
885
+ xS2[r2 >> 16 & 0xff] ^
886
+ xS3[r2 >> 24 & 0xff]
887
+ t1 = xS0[r3 >> 24 & 0xff] ^
888
+ xS1[r3 & 0xff] ^
889
+ xS2[r3 >> 8 & 0xff] ^
890
+ xS3[r3 >> 16 & 0xff]
891
+
892
+ r0 = r0 >> 31 & 0x1 | mask32(r0 << 1)
893
+ r0 ^= mask32(t0 + t1 + k[24])
894
+
895
+ r1 ^= mask32(t0 + mask32(t1 << 1) + k[25])
896
+ r1 = r1 >> 1 & 0x7fffffff | mask32(r1 << 31)
897
+
898
+
899
+ # i = 3
900
+ t0 = xS0[r0 & 0xff] ^
901
+ xS1[r0 >> 8 & 0xff] ^
902
+ xS2[r0 >> 16 & 0xff] ^
903
+ xS3[r0 >> 24 & 0xff]
904
+ t1 = xS0[r1 >> 24 & 0xff] ^
905
+ xS1[r1 & 0xff] ^
906
+ xS2[r1 >> 8 & 0xff] ^
907
+ xS3[r1 >> 16 & 0xff]
908
+
909
+ r2 = r2 >> 31 & 0x1 | mask32(r2 << 1)
910
+ r2 ^= mask32(t0 + t1 + k[22])
911
+
912
+ r3 ^= mask32(t0 + mask32(t1 << 1) + k[23])
913
+ r3 = r3 >> 1 & 0x7fffffff | mask32(r3 << 31)
914
+
915
+ t0 = xS0[r2 & 0xff] ^
916
+ xS1[r2 >> 8 & 0xff] ^
917
+ xS2[r2 >> 16 & 0xff] ^
918
+ xS3[r2 >> 24 & 0xff]
919
+ t1 = xS0[r3 >> 24 & 0xff] ^
920
+ xS1[r3 & 0xff] ^
921
+ xS2[r3 >> 8 & 0xff] ^
922
+ xS3[r3 >> 16 & 0xff]
923
+
924
+ r0 = r0 >> 31 & 0x1 | mask32(r0 << 1)
925
+ r0 ^= mask32(t0 + t1 + k[20])
926
+
927
+ r1 ^= mask32(t0 + mask32(t1 << 1) + k[21])
928
+ r1 = r1 >> 1 & 0x7fffffff | mask32(r1 << 31)
929
+
930
+ # i = 2
931
+ t0 = xS0[r0 & 0xff] ^
932
+ xS1[r0 >> 8 & 0xff] ^
933
+ xS2[r0 >> 16 & 0xff] ^
934
+ xS3[r0 >> 24 & 0xff]
935
+ t1 = xS0[r1 >> 24 & 0xff] ^
936
+ xS1[r1 & 0xff] ^
937
+ xS2[r1 >> 8 & 0xff] ^
938
+ xS3[r1 >> 16 & 0xff]
939
+
940
+ r2 = r2 >> 31 & 0x1 | mask32(r2 << 1)
941
+ r2 ^= mask32(t0 + t1 + k[18])
942
+
943
+ r3 ^= mask32(t0 + mask32(t1 << 1) + k[19])
944
+ r3 = r3 >> 1 & 0x7fffffff | mask32(r3 << 31)
945
+
946
+ t0 = xS0[r2 & 0xff] ^
947
+ xS1[r2 >> 8 & 0xff] ^
948
+ xS2[r2 >> 16 & 0xff] ^
949
+ xS3[r2 >> 24 & 0xff]
950
+ t1 = xS0[r3 >> 24 & 0xff] ^
951
+ xS1[r3 & 0xff] ^
952
+ xS2[r3 >> 8 & 0xff] ^
953
+ xS3[r3 >> 16 & 0xff]
954
+
955
+ r0 = r0 >> 31 & 0x1 | mask32(r0 << 1)
956
+ r0 ^= mask32(t0 + t1 + k[16])
957
+
958
+ r1 ^= mask32(t0 + mask32(t1 << 1) + k[17])
959
+ r1 = r1 >> 1 & 0x7fffffff | mask32(r1 << 31)
960
+
961
+ # i = 1
962
+ t0 = xS0[r0 & 0xff] ^
963
+ xS1[r0 >> 8 & 0xff] ^
964
+ xS2[r0 >> 16 & 0xff] ^
965
+ xS3[r0 >> 24 & 0xff]
966
+ t1 = xS0[r1 >> 24 & 0xff] ^
967
+ xS1[r1 & 0xff] ^
968
+ xS2[r1 >> 8 & 0xff] ^
969
+ xS3[r1 >> 16 & 0xff]
970
+
971
+ r2 = r2 >> 31 & 0x1 | mask32(r2 << 1)
972
+ r2 ^= mask32(t0 + t1 + k[14])
973
+
974
+ r3 ^= mask32(t0 + mask32(t1 << 1) + k[15])
975
+ r3 = r3 >> 1 & 0x7fffffff | mask32(r3 << 31)
976
+
977
+ t0 = xS0[r2 & 0xff] ^
978
+ xS1[r2 >> 8 & 0xff] ^
979
+ xS2[r2 >> 16 & 0xff] ^
980
+ xS3[r2 >> 24 & 0xff]
981
+ t1 = xS0[r3 >> 24 & 0xff] ^
982
+ xS1[r3 & 0xff] ^
983
+ xS2[r3 >> 8 & 0xff] ^
984
+ xS3[r3 >> 16 & 0xff]
985
+
986
+ r0 = r0 >> 31 & 0x1 | mask32(r0 << 1)
987
+ r0 ^= mask32(t0 + t1 + k[12])
988
+
989
+ r1 ^= mask32(t0 + mask32(t1 << 1) + k[13])
990
+ r1 = r1 >> 1 & 0x7fffffff | mask32(r1 << 31)
991
+
992
+ # i = 0
993
+ t0 = xS0[r0 & 0xff] ^
994
+ xS1[r0 >> 8 & 0xff] ^
995
+ xS2[r0 >> 16 & 0xff] ^
996
+ xS3[r0 >> 24 & 0xff]
997
+ t1 = xS0[r1 >> 24 & 0xff] ^
998
+ xS1[r1 & 0xff] ^
999
+ xS2[r1 >> 8 & 0xff] ^
1000
+ xS3[r1 >> 16 & 0xff]
1001
+
1002
+ r2 = r2 >> 31 & 0x1 | mask32(r2 << 1)
1003
+ r2 ^= mask32(t0 + t1 + k[10])
1004
+
1005
+ r3 ^= mask32(t0 + mask32(t1 << 1) + k[11])
1006
+ r3 = r3 >> 1 & 0x7fffffff | mask32(r3 << 31)
1007
+
1008
+ t0 = xS0[r2 & 0xff] ^
1009
+ xS1[r2 >> 8 & 0xff] ^
1010
+ xS2[r2 >> 16 & 0xff] ^
1011
+ xS3[r2 >> 24 & 0xff]
1012
+ t1 = xS0[r3 >> 24 & 0xff] ^
1013
+ xS1[r3 & 0xff] ^
1014
+ xS2[r3 >> 8 & 0xff] ^
1015
+ xS3[r3 >> 16 & 0xff]
1016
+
1017
+ r0 = r0 >> 31 & 0x1 | mask32(r0 << 1)
1018
+ r0 ^= mask32(t0 + t1 + k[8])
1019
+
1020
+ r1 ^= mask32(t0 + mask32(t1 << 1) + k[9])
1021
+ r1 = r1 >> 1 & 0x7fffffff | mask32(r1 << 31)
1022
+
1023
+ [mask32(k[0] ^ r2), mask32(k[1] ^ r3), mask32(k[2] ^ r0), mask32(k[3] ^ r1)].pack("V4")
1024
+ end
1025
+
1026
+ private
1027
+
1028
+ # The (12, 8) Reed Solomon code has the generator polynomial:
1029
+ #
1030
+ # g(x) = x^4 + (a + 1/a) * x^3 + a * x^2 + (a + 1/a) * x + 1
1031
+ #
1032
+ # where the coefficients are in the finite field GF(2^8) with a modular
1033
+ # polynomial a^8+a^6+a^3+a^2+1. To generate the remainder, we have to
1034
+ # start with a 12th order polynomial with our eight input bytes as the
1035
+ # coefficients of the 4th to 11th terms:
1036
+ #
1037
+ # m[7] * x^11 + m[6] * x^10 ... + m[0] * x^4 + 0 * x^3 +... + 0
1038
+ #
1039
+ # We then multiply the generator polynomial by m[7]*x^7 and subtract it
1040
+ # (XOR in GF(2^8)) from the above to eliminate the x^7 term (the
1041
+ # arithmetic on the coefficients is done in GF(2^8)). We then multiply
1042
+ # the generator polynomial by m[6]*x^6 and use this to remove the x^10
1043
+ # term, and so on until the x^4 term is removed, and we are left with:
1044
+ #
1045
+ # r[3] * x^3 + r[2] * x^2 + r[1] 8 x^1 + r[0]
1046
+ #
1047
+ # which give the resulting 4 bytes of the remainder. This is equivalent
1048
+ # to the matrix multiplication described in the Twofish paper, but is
1049
+ # much faster.
1050
+ def mds_rem(a, b)
1051
+
1052
+ # use constant G_MOD => 0x14d
1053
+
1054
+ t, u = 0, 0
1055
+
1056
+ # No gain by unrolling this loop.
1057
+ 8.times do
1058
+ t = b >> 24
1059
+
1060
+ # Shift the others up.
1061
+ b = mask32(b << 8) | (a >> 24)
1062
+ a = mask32(a << 8)
1063
+
1064
+ u = mask32(t << 1)
1065
+
1066
+ # Subtract the modular polynomial on overflow.
1067
+ u ^= 0x14d unless (t & 0x80).zero?
1068
+
1069
+ # Remove t * (a * x^2 + 1).
1070
+ b ^= t ^ mask32(u << 16)
1071
+
1072
+ # Form u = a*t + t/a = t*(a + 1/a).
1073
+ u ^= 0x7fffffff & (t >> 1)
1074
+
1075
+ # Add the modular polynomial on underflow.
1076
+ u ^= 0xa6 unless (t & 0x01).zero?
1077
+
1078
+ # Remove t * (a + 1/a) * (x^3 + x).
1079
+ b ^= mask32(u << 24) | mask32(u << 8)
1080
+
1081
+ end
1082
+
1083
+ [ b >> 24, b >> 16 & 0xff, b >> 8 & 0xff, b & 0xff ]
1084
+ end
1085
+
1086
+ # Retain only lowest 32 bits of the given integer.
1087
+ def mask32(x)
1088
+ x & 0xffffffff
1089
+ end
1090
+
1091
+ # Generates a random initialization vector of the given length.
1092
+ # Warning: use Ruby standard library Kernel#rand.
1093
+ def generate_iv(block_size)
1094
+ Array.new(block_size).
1095
+ map{ |x| rand(256) }.
1096
+ pack("C#{block_size}")
1097
+ end
1098
+
1099
+ end
1100
+
1101
+ # Encryption modes.
1102
+ #
1103
+ # The only currently implemented modes are ECB (Electronic Code Book)
1104
+ # and CBC (Cipher Block Chaining).
1105
+ module Mode
1106
+
1107
+ ECB = :ecb
1108
+ CBC = :cbc
1109
+ ALL = [ CBC, ECB ]
1110
+ DEFAULT = ECB
1111
+
1112
+ # Takes a string or symbol and returns the lowercased
1113
+ # symbol representation if this is a recognized mode.
1114
+ # Otherwise, throws ArgumentError.
1115
+ def Mode::validate(mode)
1116
+ mode_sym = mode.nil? ? DEFAULT : mode.to_s.downcase.to_sym
1117
+ raise ArgumentError, "unknown cipher mode #{mode.inspect}" unless ALL.include? mode_sym
1118
+ mode_sym
1119
+ end
1120
+
1121
+ end
1122
+
1123
+ # Implements padding modes to make plaintext into a complete
1124
+ # number of blocks before encryption and to remove that padding
1125
+ # after successful decryption.
1126
+ #
1127
+ # The only implemented padding schemes are :none and
1128
+ # :zero_byte. Note that zero byte padding is potentially
1129
+ # dangerous because if the plaintext terminates in
1130
+ # zero bytes then these will be erroneously removed by #unpad.
1131
+ # A more sensible padding scheme should be used in this case.
1132
+ module Padding
1133
+
1134
+ NONE = :none
1135
+ ZERO_BYTE = :zero_byte
1136
+ ALL = [ NONE, ZERO_BYTE ]
1137
+ DEFAULT = NONE
1138
+
1139
+ # Takes a string or symbol and returns the lowercased
1140
+ # symbol representation if this is a recognized padding scheme.
1141
+ # Otherwise, throws ArgumentError.
1142
+ def Padding::validate(scheme)
1143
+ scheme_sym = scheme.nil? ? DEFAULT : scheme.to_s.downcase.to_sym
1144
+ raise ArgumentError, "unknown padding scheme #{scheme.inspect}" unless ALL.include? scheme_sym
1145
+ scheme_sym
1146
+ end
1147
+
1148
+ # Pad the given plaintext to a complete number of blocks. If
1149
+ # the padding scheme is :none and the plaintext is not a whole
1150
+ # number of blocks then ArgumentError is thrown.
1151
+ def Padding::pad(plaintext, block_size, scheme=DEFAULT)
1152
+ scheme_sym = validate(scheme)
1153
+ remainder = plaintext.length % block_size
1154
+ case scheme_sym
1155
+ when NONE
1156
+ raise ArgumentError, "no padding scheme specified and plaintext length is not a multiple of the block size" unless remainder.zero?
1157
+ plaintext.dup
1158
+ when ZERO_BYTE
1159
+ unless remainder.zero?
1160
+ plaintext.dup << "\0" * (block_size - remainder)
1161
+ end
1162
+ end
1163
+ end
1164
+
1165
+ # Unpad the given plaintext using the given scheme.
1166
+ def Padding::unpad(plaintext, block_size, scheme=DEFAULT)
1167
+ scheme_sym = validate(scheme)
1168
+ case scheme_sym
1169
+ when NONE
1170
+ plaintext.dup
1171
+ when ZERO_BYTE
1172
+ plaintext.dup.sub(/\000+\Z/, '')
1173
+ end
1174
+ end
1175
+
1176
+ end
1177
+