twofish 1.0.0
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.
- data/LICENSE +27 -0
- data/README.rdoc +130 -0
- data/Rakefile +35 -0
- data/lib/twofish.rb +1177 -0
- data/test/test_twofish.rb +290 -0
- 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
|
+
|