twofish 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|